m基于FPGA的GFDM调制解调系统verilog实现,包含testbench仿真测试文件

22 阅读5分钟

1.算法仿真效果

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

5714de3ea2609ef09353125f0a93ffc6_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.jpg  

GFDM调制信号放大:

0a2e40785f90399a264108c1b1ebbbc3_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.jpg  

GFDM解调信号放大:

539a4ce6f102bdbacb6dc840a6758843_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.jpg  

系统RTL结构图如下:

13111a8017fe0db7ba58fe21135f7fd3_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.jpg  

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

        随着通信技术的不断发展,人们对数据传输速率和频谱效率的要求越来越高。为了满足这些需求,一种名为广义频分复用(GFDM)的新型调制技术应运而生。GFDM具有灵活的子载波间隔和符号时间长度,能够在各种复杂环境中实现高效的数据传输。

 

       GFDM是一种基于子载波的多载波调制技术,通过对子载波进行调制和解调来实现数据传输。与传统的正交频分复用(OFDM)相比,GFDM具有更灵活的子载波间隔和符号时间长度,可以更好地适应不同的信道环境。

 

2.1 子载波调制

       在GFDM中,每个子载波可以采用不同的调制方式,如BPSK、QPSK、16QAM等。调制符号在子载波上进行传输,子载波的间隔可以根据需要进行调整。调制符号在每个子载波上的传输时间称为符号时间,符号时间的长度也可以根据需要进行调整。

 

       在GFDM中,每个子载波可以采用不同的调制方式。以BPSK为例,调制公式为:s_k(t) = a_k * cos(2πf_k t + φ_k)其中,s_k(t)表示第k个子载波上的调制信号,a_k表示调制符号的幅度,f_k表示第k个子载波的频率,φ_k表示第k个子载波的相位。

 

2.2 脉冲成型滤波

       在GFDM中,为了减小子载波间的干扰,通常在调制符号上施加一个脉冲成型滤波器。该滤波器可以在时域和频域上实现良好的局部化特性,从而减小子载波间的干扰。常用的脉冲成型滤波器包括矩形滤波器、高斯滤波器和升余弦滤波器等。

 

      在GFDM中,通常在调制符号上施加一个脉冲成型滤波器。以矩形滤波器为例,滤波公式为:g(t) = rect(t/T_s)其中,g(t)表示脉冲成型滤波器,rect(t/T_s)表示矩形函数,T_s表示符号时间长度。

 

2.3 GFDM信号生成

       在GFDM中,经过子载波调制和脉冲成型滤波后的信号称为GFDM符号。一个GFDM符号由多个子载波组成,每个子载波上传输一个调制符号。多个GFDM符号组成一个GFDM帧,用于在信道上进行传输。

 

       在GFDM中,经过子载波调制和脉冲成型滤波后的信号称为GFDM符号。一个GFDM符号由多个子载波组成,每个子载波上传输一个调制符号。以N个子载波为例,GFDM信号生成公式为:x(t) = ∑_{k=0}^{N-1} s_k(t) * g(t - kT_s)其中,x(t)表示GFDM信号,s_k(t)表示第k个子载波上的调制信号,g(t)表示脉冲成型滤波器,T_s表示符号时间长度。

 

3.Verilog核心程序 ``timescale 1ns / 1ps

//

// Company:

// Engineer:

//

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//

module TEST_GFDM;

reg             i_clk;        

reg             i_clk2x;         

reg             i_rst;          

reg             i_fft_start;               

reg             i_fft_end;   

reg             i_fft_en;  

reg signed[15:0]i_I;                 

reg signed[15:0]i_Q;   

 

wire  o_GFDM_start;

wire  o_GFDM_ends ;

wire  o_GFDM_enable;

wire signed[31:0]o_GFDM_I;                 

wire signed[31:0]o_GFDM_Q;

 

 

wire  o_deGFDM_start;

wire  o_deGFDM_ends ;

wire  o_deGFDM_enable;

wire signed[31:0]o_deGFDM_I;                 

wire signed[31:0]o_deGFDM_Q;  

 

GFDM GFDM_u(

                .i_clk         (i_clk),

                .i_clk2x       (i_clk2x),

                .i_rst         (i_rst),

                

                .i_fft_start   (i_fft_start),

                .i_fft_end     (i_fft_end),

                .i_fft_en      (i_fft_en),

                .i_I           (i_I),

                .i_Q           (i_Q),

                

                .o_GFDM_start       (o_GFDM_start),

                .o_GFDM_ends        (o_GFDM_ends),

                .o_GFDM_enable      (o_GFDM_enable),

                .o_GFDM_I           (o_GFDM_I),

                .o_GFDM_Q           (o_GFDM_Q),

                

                .o_deGFDM_start     (o_deGFDM_start),

                .o_deGFDM_ends      (o_deGFDM_ends),

                .o_deGFDM_enable    (o_deGFDM_enable),

                .o_deGFDM_I         (o_deGFDM_I),

                .o_deGFDM_Q         (o_deGFDM_Q)

                );

 

reg [15:0]cnts;

always @(posedge i_clk or posedge i_rst)

begin

     if(i_rst)

     begin

     cnts       <= 16'd0;

         i_I <= -1000;

         i_Q <= 1000;

     end

else begin

          

          if(i_fft_en == 1'b1)

          begin

          cnts       <= cnts+16'd1;

          

              if(cnts>=16'd400 & cnts<=16'd1648)

              begin

                  i_I <= ~i_I;

                  if (cnts[0]==1'b1)

                  i_Q <= ~i_Q;

                  else

                  i_Q <=  i_Q;

              end    

          end

          else begin

          cnts       <= 16'd0;

          i_I <= -1000;

          i_Q <= 1000;

          end

     end

end

reg [19:0]cnts2;

always @(posedge i_clk or posedge i_rst)

begin

     if(i_rst)

     begin

     cnts2        <= 20'd0;

     i_fft_start<=1'b0;

     i_fft_en    <=1'b0;

     i_fft_end  <=1'b0;

     end

else begin

          if(cnts2==20'd30000)

          cnts2  <= 20'd0;

          else

          cnts2  <= cnts2 + 20'd1;

 

          if(cnts2==20'd0)

          begin

             i_fft_start<=1'b1;

             i_fft_en    <=1'b0;

             i_fft_end  <=1'b0;

          end

          if(cnts2==20'd1)

          begin

             i_fft_start<=1'b1;

             i_fft_en    <=1'b0;

             i_fft_end  <=1'b0;

          end

          if(cnts2==20'd2)

          begin

             i_fft_start<=1'b1;

             i_fft_en    <=1'b0;

             i_fft_end  <=1'b0;

          end

          if(cnts2==20'd3)

          begin

             i_fft_start<=1'b1;

             i_fft_en    <=1'b0;

             i_fft_end  <=1'b0;

          end

          

          if(cnts2==20'd4)

          begin

             i_fft_start<=1'b0;

             i_fft_en    <=1'b0;

             i_fft_end  <=1'b0;

          end

          if(cnts2>=20'd5 & cnts2<=20'd4+2047)

          begin

             i_fft_start<=1'b0;

             i_fft_en    <=1'b1;

             i_fft_end  <=1'b0;

          end

          

          if(cnts2==20'd4+2048)

          begin

             i_fft_start<=1'b0;

             i_fft_en    <=1'b1;

             i_fft_end  <=1'b1;

          end

          

          if(cnts2>20'd4+2048)

          begin

             i_fft_start<=1'b0;

             i_fft_en    <=1'b0;

             i_fft_end  <=1'b0;

          end

     

     

     

     end

end

initial

begin

    i_clk2x= 1'b1;

    i_clk = 1'b1;

    i_rst = 1'b1;

    #1000

    i_rst = 1'b0;

end

always #10 i_clk=~i_clk;

always #5 i_clk2x=~i_clk2x;

endmodule`