1.PM的模拟调制过程
PM信号是一种相位调制信号,其携带的信息保存在其信号的相位中,通过改变载波的相位来实现基带数据的传输。
其函数表达式如下:
\[s(t) = A*cos(w_c*t + K_f*m(t))
\]
其中:
\(A\):表示载波幅度。
\(m(t)\):表示基带信号。
\(w_c\):表示载波信号角度增量。
\(K_f\):是调制灵敏度。
正交调制法公式如下:
\[I(t) = cos(K_f*m(t)) \\
Q(t) = sin(K_f*m(t)) \\
s(t) = A*(I(t)*cos(w_c*t) - Q(t)*sin(w_c*t))
\]
2.PM的数字正交解调
原理:
对于I路,其中\(\varphi\)表示调制载波与解调载波的相位差:
\[\begin{array}{flalign}
I(n) & = LPF(s(n)*cos(w_c*n + \varphi)) \\& = \frac{cos(K_f*m(n))*cos(\varphi) + sin(K_f*m(n))*sin(\varphi)}{2} \\& = \frac{1}{2}*cos(K_f*m(n) - \varphi)
\end{array}
\]
对于Q路:
\[\begin{array}{flalign}
Q(n) & = LPF(s(n)*sin(w_c*n + \varphi)) \\& = \frac{cos(K_f*m(n))*sin(\varphi) - sin(K_f*m(n))*cos(\varphi)}{2} \\& = \frac{1}{2}*sin(K_f*m(n) - \varphi)
\end{array}
\]
同时:
\[\begin{array}{flalign}
&\ \frac{Q(n)}{I(n)} = \frac{sin(K_f* m(n)- \varphi)}{cos(K_f* m(n)- \varphi)} = tan(K_f* m(n) - \varphi) \\
&\ M(n) = arctan(\frac{Q(n)}{I(n)}) = K_f* m(n) - \varphi\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space
(\frac{Q(n)}{I(n)}) \in (-\pi/2\space\space\space\space\pi/2)
\end{array}
\]
注:上式推算中使用了arctan
函数,其中arctan
的输入范围\((-\pi/2\space\space\space\space\pi/2)\)。当范围超过将计算错误。所以将使用MATLAB的atan2
函数进行计算。
\[M(n) = atan2(Q(n),I(n)) = K_f*m(n)- \varphi
\]
3.MATLAB仿真
仿真代码:
fs = 20000;%采样率
l = 1E3;%基带信号点数
f = 100;%基带信号
f_c = 500;%载波信号
t = 0:1/fs:(l-1)/fs;
mt = cos(2*pi*f*t);
kf = 2;
fi = pi/3;
%% IQ信号
I = cos(kf*mt + fi);
Q = sin(kf*mt + fi);%% 调制数据
mod_data = I.*cos(2*pi*f_c*t) - Q.*sin(2*pi*f_c*t);%% 解调
demod = atan2(Q,I);
for i = 2:1:length(demod)if(demod(i) >= pi)demod(i) = demod(i) - pi*2; elseif(demod(i) <= -pi)demod(i) = demod(i) + pi*2; else demod(i) = demod(i); end
end
%% 去直流
dc_signal = sum(demod)/l;
demod0 = demod-dc_signal;
%% 保存IQ数据FPGA使用仿真
fid = fopen('PM.txt','w');
for i = 1:lfprintf(fid,'%d %d\n',floor(I(i)* (2^13)),floor(Q(i)* (2^13)));
end
fclose(fid);%% 绘制
figure
time = 4;
subplot(time,1,1);
plot(mt);
title('基带数据');subplot(time,1,2);
plot(mod_data);
title('调制数据');subplot(time,1,3);
plot(demod);
title('解调数据');subplot(time,1,4);
plot(demod0);
title('解调数据(去直流)');
结果:
4.FPGA解调
逻辑代码:
module pm_demod(input clk ,input rst ,//解调参数input i_valid ,input [15:0] i_data_i ,input [15:0] i_data_q ,output o_rdy ,output [15:0] o_data );wire pm_valid ;wire [23:0] pm_i ;wire [23:0] pm_q ;wire pm_rdy ;wire [47 : 0] m_axis_dout_tdata ;//AM 解调assign pm_valid = i_valid ;assign pm_i = {{8{i_data_i[15]}},i_data_i} ;assign pm_q = {{8{i_data_q[15]}},i_data_q} ; cordic_translate cordic_translate (.aclk (clk ), // input wire aclk.s_axis_cartesian_tvalid (pm_valid ), // input wire s_axis_cartesian_tvalid.s_axis_cartesian_tdata ({pm_i,pm_q} ), // input wire [47 : 0] s_axis_cartesian_tdata.m_axis_dout_tvalid (pm_rdy ), // output wire m_axis_dout_tvalid.m_axis_dout_tdata (m_axis_dout_tdata ) // output wire [47 : 0] m_axis_dout_tdata);assign o_data = m_axis_dout_tdata[24 +:16];assign o_rdy = pm_rdy;endmodule
仿真代码:
module tb_pm_demod();reg clk;reg rst;initial beginclk <= 0;rst <= 1;#300rst <= 0;endalways #(100/2) clk <=~clk;reg valid;reg [15:0] din_i;reg [15:0] din_q;wire o_rdy ;wire [15:0] o_data ;pm_demod pm_demod(.clk (clk),.rst (rst),.i_valid (valid),.i_data_i (din_i),.i_data_q (din_q),.o_rdy (o_rdy ),.o_data (o_data ));integer file_rd; //定义数据读指针integer flag;initial begin //打开读取和写入的文件,这里的路径要对 file_rd = $fopen("PM.txt","r");end reg [15:0] cnt;always @(posedge clk)beginif(rst)begindin_i <= 0;din_q <= 0;cnt <= 0;valid <= 0;endelse if(cnt <= 1000)beginvalid <= 1;flag = $fscanf(file_rd,"%d %d",din_i,din_q);cnt <= cnt + 1;endelse begin$fclose(file_rd);$stop();endend
endmodule
仿真结果: