欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

基于FPGA的AM信号调制与解调详细步骤

发布时间:2025/3/15 编程问答 55 豆豆
生活随笔 收集整理的这篇文章主要介绍了 基于FPGA的AM信号调制与解调详细步骤 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

 

详细程序及原理参考原文:

FPGA学习(二)——实现AM信号调制与解调 - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/p/37203478

 

  • 使用的软件是Vivado 2016.4
  • 实验室板卡是Nexys Video
  • 一、写在前面

    仿真可实现,VIO可用。

     

    1.本篇记录的是如何进行AM信号的调制与解调,

    其主要步骤包括:

     

  • 分频器(Frequency divider)的产生
  • 载波信号(Carrier signal)的产生
  • 调制信号(Modulated signal)的产生
  • 含直流分量(DC component)的调制信号
  • 已调信号(Modulated signal)的产生
  • 相干解调(Coherent demodulation)
  • 滤除直流分量(DC component)
  • 中间还有截位操作
  •  

    2.关于截位:

    在FPGA中,随着信号处理的层次加深,对信号进行乘、累加、滤波等运算后,可能输入时仅为8位位宽的信号会扩展成几十位位宽,位宽越宽,占用的硬件资源就越多,但位宽超过一定范围后,位宽的增宽并不会对处理精度带来显著的改善,这时就需要对信号进行截位。

    3.关于滤波器设计

    两种方法:

    一是相干解调时需要低通滤波器;

    二是可采用对已调信号取绝对值的方式(包络检波)也需要低通滤波器。

     

    二、对过程的要求:

    (1)载波信号频率范围:1M-10MHz,分辨率0.01MHz;

    (2)调制信号为单频正弦波信号,频率范围:1kHz-10kHz,分辨率0.01kHz;

    (3)调制深度0-1.0,步进0.1,精度优于5%;

    (4)调制信号和解调信号位宽为___8___位,其他信号位宽自定义,解调误差优于1%(可利用MATLAB对数据进行验证);

     

    三、原理分析

    1.调制与解调原理

    //已调信号输出:out=Add_1_out*dds_zb_out

    //含直流分量的调制信号:Add_1_out=mult_1_out+1280(8位调制信号的幅值)

    //可控的直流分量输出:mult_1_out=dds_tz_out*ma(Ma/10为调制深度)

    //载波信号输出:DDS>>dds_compiler_zb>>dds_zb_out>>频率控制字fre_word_zb,16bits,输出位宽8bits

    //无直流分量的调制信号输出:DDS>>dds_compiler_tz>>dds_tz_out>>频率控制字fre_word_tz,16bits,输出位宽8bits

     

    2.根据要求设计信号参数

    1)载波信号频率范围:1M-10MHz,分辨率0.01MHz

    DDS工作时钟选择40MHz,dds_zb_out:频率控制字16位,输出8位,原理见:

    子木:FPGA学习(一)——产生频率可控的正弦波​zhuanlan.zhihu.com

    (2)调制信号为单频正弦波信号,频率范围:1kHz-10kHz,分辨率0.01kHz

    DDS工作时钟选择10MHz,dds_tz_out:频率控制字为16位,输出8位

    (3)调制深度0-1.0,步进0.1,精度优于5%;

    ma定义就不多说了,这里得到的方法是在已知调制信号输出位宽的前提下(已调信号幅值绝对值为128):

    其中Ma取值为1~10,之间的整数。

    (4)调制信号和解调信号位宽为___8___位,其他信号位宽自定义,解调误差优于1%(可利用MATLAB对数据进行验证);

    使用截位的方法,使解调信号输出8位。

    四、分频器(Frequency divider)设计

    由于DDS工作时钟选择40MHz,将100MHz分为40MHz和10MHz即可。详见下面这篇中的分频器设计部分:

    子木:FPGA学习(一)——产生频率可控的正弦波​zhuanlan.zhihu.com

    五、产生载波信号(Carrier signal)

    1.实现方式:DDS IP核

     

    2.变量名:

    工作时钟:clk_40m

    载波频率控制字:fre_word_zb

    载波输出信号:dds_zb_out

    原理见上一篇!

    六、产生无直流分量(DC component)调制信号(Modulated signal)

    1.实现方式:DDS IP核

     

    2.变量名:

    工作时钟:clk_10m

    调制信号频率控制字:sfre_word_tz

    无直流分量的调制信号输出:dds_tz_out

    原理见上一篇!

    七、产生含直流分量的调制信号

    1.由Ma控制调制信号,再加上固定的直流分量即可。

    ma  dds_tz_out+1280。

     

    2.实现方式:乘法器 IP核:mult_1和加法器IP核:Add

     

    3.变量名:

    调制深度控制变量:ma

    Ma控制的调制信号输出:mult_1_out

    直流分量:1280

    含直流分量的调制信号输出:Add_1_out

    八、输出已调信号(Modulated signal)

    1.载波与含直流分量的调制信号相乘

     

    2.实现方式:乘法器IP核:mult_2

     

    3.变量名:

    含直流分量的调制信号输入:Add_1_out

    载波输入信号:dds_zb_out

    已调信号输出:out

    九、相干解调(或包络检波)(Coherent demodulation)

    1.相干解调:载波与已调信号相乘

     

    1.2实现方式:乘法器IP核:DM_Mul

     

    1.3变量名:

    已调信号输入:AM_out

    载波输入信号:carrier_out

    解调信号输出:DM_out

    2.包络检波:对输出的已调波截位为8位,再取绝对值。

    2.1实现方式:取绝对值

    2.2变量名:

    截位输出:AM_out_clk(8位)

    取绝对值后的输出:AM_abs(8位)

    十、滤除高频分量(High frequency component)

    1.FIR低通滤波器:设置阶数和输入输出信号位宽

     

    2.实现方式:

    2.1 MATLAB生成coe文件

    2.2 FIR IP核:fir

     

    3.变量名:

    滤波器输信号:{8'b0,AM_abs} (由设置输入信号位宽决定)

    滤波器输出信号:signal_dm

     

    十一、对滤波器输出信号进行截位

     

    reg [7:0] signal_dm_8; always @ (posedge sysclk) beginsignal_dm_8 <= signal_dm[21:14]; end

    十二、滤除直流

    1.根据波形,设置可由vio控制的变量,改变输出的解调信号,使解调误差最低。

    2.具体原理见程序

    十三、VIO设置

    四个通过vio控制的输入变量:

    调制深度:ma

    载波频率控制字:fre_word_zb

    调制信号频率控制字:fre_word_tz

    解调信号中的直流:dc

    消除失真的参数:Au

    十四、ILA设置

    1.需要用ila观测的输出(括号里的变量)

    滤波器输出信号// .probe5(signal_dm)

    调制信号// .probe0(dds_tz_out), // input wire [7:0] probe0

    已调信号的截位输出// .probe1(AM_out_clk), // input wire [7:0] probe1

    滤波器输出信号的截位输出// .probe2(signal_dm_8), // input wire [7:0] probe2

    去除直流的解调信号// .probe3(signal_dm_8_ac), // input wire [7:0] probe3

    无失真的解调信号// .probe4(signal_dm_8_ac_ma), // input wire [7:0] probe4

    2.ila观测深度应尽量大才能更好的观察波形

    十三、仿真波形

     

     

     

     

     

    下面是单独ma=1时的输出,截位还未来得及修改。

     

    十三、所有代码

     

    1.主程序

    `timescale 1ns / 1ps // // Company: // Engineer: 子木QQ2417677728 // // Create Date: 2018/05/26 15:48:17 // Design Name: // Module Name: LSY_2015105408 // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // //module LSY_2015105408(input wire sysclk, input wire [15:0] fre_word_zb,//610.3515625 input wire [15:0] fre_word_tz,//152.58789062 input wire [3:0] ma, output wire [20:0] out );wire clk_40m;wire clk_10m;clk_wiz_0 clk(// Clock out ports.clk_out1(clk_40m), // output clk_out1.clk_out2(clk_10m), // output clk_out2// Clock in ports.clk_in1(sysclk)); // input clk_in1// wire [15 : 0] fre_word_zb; //下载恢复wire [7 : 0] dds_zb_out;dds_compiler_zb dds_zb (.aclk(clk_40m), // input wire aclk.s_axis_phase_tvalid(1), // input wire s_axis_phase_tvalid.s_axis_phase_tdata(fre_word_zb), // input wire [15 : 0] s_axis_phase_tdata.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid.m_axis_data_tdata(dds_zb_out) // output wire [7 : 0] m_axis_data_tdata);// wire [15 : 0] fre_word_tz; //下载恢复wire [7 : 0] dds_tz_out;dds_compiler_tz dds_tz (.aclk(clk_10m), // input wire aclk.s_axis_phase_tvalid(1), // input wire s_axis_phase_tvalid.s_axis_phase_tdata(fre_word_tz), // input wire [15 : 0] s_axis_phase_tdata.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid.m_axis_data_tdata(dds_tz_out) // output wire [7 : 0] m_axis_data_tdata);// wire [3:0] ma; //下载恢复wire [11:0] mult_1_out; //修改位宽mult_1 mult_1 (.CLK(sysclk), // input wire CLK.A(ma), // input wire [3 : 0] A.B(dds_tz_out), // input wire [7 : 0] B //修改位宽.P(mult_1_out) // output wire [11 : 0] P //修改位宽);wire [12:0] Add_1_out;Add Add_1 (.A(mult_1_out), // input wire [11 : 0] A //修改位宽.B(12'd1280), // input wire [11 : 0] B.CLK(sysclk), // input wire CLK.S(Add_1_out) // output wire [12 : 0] S //修改位宽); // wire [20:0] out; //下载恢复 mult_2 mult_2 (.CLK(sysclk), // input wire CLK.A(Add_1_out), // input wire [12 : 0] A //修改位宽.B(dds_zb_out), // input wire [7 : 0] B //修改位宽.P(out) // output wire [20 : 0] P //修改位宽); reg [7:0] AM_out_clk;always @ (posedge sysclk)beginAM_out_clk <= {out[20],out[18:12]};end reg [7:0] AM_abs; always @ (posedge sysclk)beginif(AM_out_clk[7])AM_abs<= {1'b0,~AM_out_clk[6:0]};elseAM_abs <= AM_out_clk;endwire [31 : 0] signal_dm; fir fir (.aclk(sysclk), // input wire aclk.s_axis_data_tvalid(1), // input wire s_axis_data_tvalid.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready.s_axis_data_tdata({8'b0,AM_abs}), // input wire [15 : 0] s_axis_data_tdata.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid.m_axis_data_tdata(signal_dm) // output wire [31 : 0] m_axis_data_tdata ); reg [7:0] signal_dm_8_ac; reg [7:0] signal_dm_8; always @ (posedge sysclk) beginsignal_dm_8 <= signal_dm[21:14];signal_dm_8_ac <= signal_dm_8 - (6'd46) ; end//wire [7:0] dc; //always @ (posedge sysclk) //beginsignal_dm_8_ac <= signal_dm_8 - dc ; // signal_dm_8_ac <= signal_dm_8 - (6'd32) ; //endreg [7:0] signal_dm_8_ac_ma; always @ (posedge sysclk) begin // signal_dm_8_ac_ma <= signal_dm_8_ac*Au ;signal_dm_8_ac_ma <= signal_dm_8_ac*(3'd5) ; end//vio_0 vio ( // .clk(sysclk), // input wire clk // .probe_out0(ma), // output wire [3 : 0] probe_out0 // .probe_out1(fre_word_zb), // output wire [15 : 0] probe_out1 // .probe_out2(fre_word_tz), // output wire [15 : 0] probe_out2 // .probe_out3(dc), // output wire [7 : 0] probe_out3 // .probe_out4(Au) // output wire [7 : 0] probe_out4 //);//ila_0 ila ( // .clk(sysclk), // input wire clk// .probe0(dds_tz_out), // input wire [7:0] probe0 // .probe1(AM_out_clk), // input wire [7:0] probe1 // .probe2(signal_dm_8), // input wire [7:0] probe2 // .probe3(signal_dm_8_ac), // input wire [7:0] probe3 // .probe4(signal_dm_8_ac_ma), // input wire [7:0] probe4 // .probe5(signal_dm) // input wire [31:0] probe5 //);endmodule

     

    2.仿真程序

    `timescale 1ns / 1psmodule tb();reg sysclk;reg [3:0] Ma;reg [15 : 0] word_zb;reg [15 : 0] word_tz;wire [20 : 0] out;LSY_2015105408 test(.sysclk(sysclk),.ma(Ma),.fre_word_zb(word_zb),.fre_word_tz(word_tz),.out(out));initialbeginsysclk = 0;forever#5 sysclk = ~sysclk;endinitialbegin#0 word_zb = 16'd16384; word_tz = 16'd13;Ma = 4'd5;end endmodule

     

    3.约束文件

    set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports sysclk]create_clock -period 10.000 -name sysclk -waveform {0.000 5.000} [get_ports *sysclk*]

    总结

    以上是生活随笔为你收集整理的基于FPGA的AM信号调制与解调详细步骤的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。