我是靠谱客的博主 正直电源,这篇文章主要介绍基于FPGA的AM信号调制与解调详细步骤 详细程序及原理参考原文:FPGA学习(二)——实现AM信号调制与解调 - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/p/37203478,现在分享给大家,希望可以做个参考。

 

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

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

 

  1. 使用的软件是Vivado 2016.4
  2. 实验室板卡是Nexys Video

一、写在前面

仿真可实现,VIO可用。

 

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

其主要步骤包括:

 

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

 

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

 

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

 

复制代码
1
2
3
4
5
6
reg [7:0] signal_dm_8; always @ (posedge sysclk) begin signal_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.主程序

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
`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) begin AM_out_clk <= {out[20],out[18:12]}; end reg [7:0] AM_abs; always @ (posedge sysclk) begin if(AM_out_clk[7]) AM_abs<= {1'b0,~AM_out_clk[6:0]}; else AM_abs <= AM_out_clk; end wire [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) begin signal_dm_8 <= signal_dm[21:14]; signal_dm_8_ac <= signal_dm_8 - (6'd46) ; end //wire [7:0] dc; //always @ (posedge sysclk) //begin signal_dm_8_ac <= signal_dm_8 - dc ; // signal_dm_8_ac <= signal_dm_8 - (6'd32) ; //end reg [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.仿真程序

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
`timescale 1ns / 1ps module 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) ); initial begin sysclk = 0; forever #5 sysclk = ~sysclk; end initial begin #0 word_zb = 16'd16384; word_tz = 16'd13;Ma = 4'd5; end endmodule

 

3.约束文件

复制代码
1
2
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信号调制与解调详细步骤 详细程序及原理参考原文:FPGA学习(二)——实现AM信号调制与解调 - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/p/37203478的全部内容,更多相关基于FPGA的AM信号调制与解调详细步骤 详细程序及原理参考原文:FPGA学习(二)——实现AM信号调制与解调内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部