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

143 阅读5分钟

1.算法仿真效果

vivado2019.2仿真结果如下:

 

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

 

将波形放大,看到如下效果:

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

 

 

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

       8FSK(8-Frequency Shift Keying)是一种常用的数字调制方法,它通过在不同的频率上发送二进制数据来进行通信。8FSK在通信系统中被广泛应用,因为它具有较高的数据传输速率和较强的抗干扰能力。

 

       在8FSK中,每个二进制位被发送在一个特定的频率上。发送频率根据发送的数据位而变化,具体地说,发送的频率根据发送的二进制位的值确定。

 

      具体地,8FSK使用8个不同的频率来表示8个不同的二进制位。频率f0到f7对应于二进制位000到111。每个频率对应于一个特定的时间间隔,称为符号时间。在一个符号时间内,数据位被发送出去。在发送端,输入的二进制数据首先被分成两个比特一组,然后根据以下规则映射到相应的频率上:

 

000 - f0

001 - f1

010 - f2

011 - f3

100 - f4

101 - f5

110 - f6

111 - f7

以上是一种常见的映射方式,但也可以使用其他的映射方式。

 

       在接收端,8FSK信号被接收并解调,以恢复原始的二进制数据。解调器需要知道每个频率对应的二进制位,以便正确地恢复数据。解调器可以使用各种方法来实现,例如滤波器、频谱分析等。

 

       8FSK调制的基本原理可以用数学公式表示。假设输入的二进制数据为b(t),发送的频率为f(t),则调频信号s(t)可以表示为:

 

s(t) = Re[b(t)exp(j2πf(t))]

 

其中Re表示取实部,j表示虚数单位,π表示圆周率。

 

       在接收端,解调器需要对接收到的信号进行解调,以恢复出原始的二进制数据。解调可以使用各种方法来实现,例如包络检波、同步检测等。其中包络检波的基本原理是检测接收信号的包络线,以恢复出原始的数据。其数学公式可以表示为:

 

b(t) = Re[s(t)exp(-j2πf(t))]

 

8FSK调制具有以下优点:

 

较高的传输速率:由于使用了多个频率进行传输,因此可以实现较高的传输速率。

较强的抗干扰能力:由于使用了频率偏移键控,因此具有较强的抗干扰能力。

适用于多径传播环境:由于使用了不同的频率进行传输,因此可以适用于多径传播环境。

实现简单:相对于其他数字调制方法,8FSK的实现较为简单。

然而,8FSK调制也存在以下缺点:

 

频带利用率较低:由于使用了多个频率进行传输,因此频带利用率较低。

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

//

 

//

 

module test_FSK;

 

reg i_clk;

reg i_rst;

reg[2:0]i_bits;

wire signed[15:0]o_carrier1;

wire signed[15:0]o_carrier2;

wire signed[15:0]o_carrier3;

wire signed[15:0]o_carrier4;

wire signed[15:0]o_carrier5;

wire signed[15:0]o_carrier6;

wire signed[15:0]o_carrier7;

wire signed[15:0]o_carrier8;

wire signed[31:0]o_de_fsk1;

wire signed[31:0]o_de_fsk2;

wire signed[31:0]o_de_fsk3;

wire signed[31:0]o_de_fsk4;

wire signed[31:0]o_de_fsk5;

wire signed[31:0]o_de_fsk6;

wire signed[31:0]o_de_fsk7;

wire signed[31:0]o_de_fsk8;

wire signed[15:0]o_fsk;

wire [2:0]o_bits;

 

FSK uut(

.i_clk(i_clk),

.i_rst(i_rst),

.i_bits(i_bits),

.o_carrier1(o_carrier1),

.o_carrier2(o_carrier2),

.o_carrier3(o_carrier3),

.o_carrier4(o_carrier4),

.o_carrier5(o_carrier5),

.o_carrier6(o_carrier6),

.o_carrier7(o_carrier7),

.o_carrier8(o_carrier8),

.o_fsk(o_fsk),

.o_de_fsk1(o_de_fsk1),

.o_de_fsk2(o_de_fsk2),

.o_de_fsk3(o_de_fsk3),

.o_de_fsk4(o_de_fsk4),

.o_de_fsk5(o_de_fsk5),

.o_de_fsk6(o_de_fsk6),

.o_de_fsk7(o_de_fsk7),

.o_de_fsk8(o_de_fsk8),

.o_bits(o_bits)

);

 

initial

begin

    i_clk = 1'b1;

    i_rst = 1'b1;

    #1000

    i_rst = 1'b0;

end

initial

begin

    i_bits= 3'b000;

    #3050

    repeat(100)

    begin

    #700

    i_bits= 3'b000;

    #900

    i_bits= 3'b011;

    #880

    i_bits= 3'b000;

    #900

    i_bits= 3'b001;

    #700

    i_bits= 3'b010;

    #800

    i_bits= 3'b100;

    #800

    i_bits= 3'b011;

    #1600

    i_bits= 3'b011;

    #1600

    i_bits= 3'b100;

    #600

    i_bits= 3'b110;

    #700

    i_bits= 3'b100;

    #600

    i_bits= 3'b101;

    #1600

    i_bits= 3'b111;

    #1800

    i_bits= 3'b010;

    #1400

    i_bits= 3'b01;

    #1400

    i_bits= 3'b101;

    #1400

    i_bits= 3'b100;

    

    #1900

    i_bits= 3'b101;

    #1700

    i_bits= 3'b101;

    #700

    i_bits= 3'b001;

    #1700

    i_bits= 3'b000;

    #1800

    i_bits= 3'b101;

    #1600

    i_bits= 3'b100;

    #1400

    i_bits= 3'b100;

    #1600

    i_bits= 3'b000;

    end

end

always #5 i_clk=~i_clk;

endmodule`