基于FPGA的AM信号调制与解调详细步骤
?
詳細程序及原理參考原文:
FPGA學習(二)——實現AM信號調制與解調 - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/p/37203478
?
一、寫在前面
仿真可實現,VIO可用。
?
1.本篇記錄的是如何進行AM信號的調制與解調,
其主要步驟包括:
?
?
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信号调制与解调详细步骤的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 量子遗传算法原理与MATLAB仿真程序
- 下一篇: 超详细的8psk调制解调通信系统讲解与仿