FM的正交解調法

超级大咸鱼發表於2024-10-05

1.FM的模擬調製過程

​ FM訊號是一種頻率調製訊號,其攜帶的資訊儲存在其訊號的頻率中,透過改變載波的頻率來實現基帶資料的傳輸。

其函式表示式如下:

\[s(t) = A*cos(w_c*t + K_f*\int m(\tau) d\tau) \]

其中:
A:表示載波幅度。
\(m(\tau)\):表示基帶訊號。
\(w_c\):表示載波訊號角度增量。
\(K_f\):是調頻靈敏度。

正交調製法公式如下:

\[\begin{array}{3} I(t) = cos(K_f*\int m(\tau) d\tau) \\ Q(t) = sin(K_f*\int m(\tau) d\tau) \\ s(t) = A*(I(t)*cos(w_c*t) - Q(t)*sin(w_c*t)) \end{array} \]

2.FM的數字正交解調

原理:

FM的正交解調法

對於I路:

\[I(n) = cos(K_f*\int m(\tau) d\tau) = cos(K_f*\sum m(n)) \]

對於Q路:

\[Q(n) = sin(K_f*\int m(\tau) d\tau) = sin(K_f*\sum m(n)) \]

同時:

\[\begin{array}{c} \frac{Q(n)}{I(n)} = \frac{sin(K_f*\sum m(n))}{cos(K_f*\sum m(n))} = tan(K_f*\sum m(n)) \space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space (K_f*\sum m(n)) \in [-\pi/2\space\space\space\space\pi/2] \\ SUM(n) = arctan(\frac{Q(n)}{I(n)}) = K_f*\sum m(n) \\ M(n) = SUM(n) - SUM(n-1) = K_f* m(n) \end{array} \]

注:上式推算中使用了tan函式,其中tan的輸入範圍\([-\pi/2\space\space\space\space\pi/2]\)。當範圍超過將計算錯誤。所以將使用MATLAB的atan2函式進行計算。

\[\begin{array}{c} SUM(n) = atan2(Q(n),I(n)) = K_f*\sum m(n) \\ M(n) = SUM(n) - SUM(n-1) = K_f* m(n) \end{array} \]

3.MATLAB模擬

模擬程式碼:

fs = 20000;%取樣率
l = 1E3;%基帶訊號點數
f = 100;%基帶訊號
f_c = 2000;%載波訊號
t = 0:1/fs:(l-1)/fs;
mt = cos(2*pi*f*t);
kf = fs * 0.4;
%% IQ訊號
I = cos(kf*cumtrapz(t,mt));
Q = sin(kf*cumtrapz(t,mt));
%% 調製資料
mod_data = I.*cos(2*pi*f_c*t) - Q.*sin(2*pi*f_c*t);
%% 解調
mmm = atan2(Q,I);
demod = zeros(1,length(mmm));
for i = 2:1:length(demod)
    demod(i) = mmm(i) - mmm(i-1);
    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

%% 儲存IQ資料FPGA使用模擬
fid = fopen('FM.txt','w');
for i = 1:l
    fprintf(fid,'%d %d\n',floor(I(i)* (2^13)),floor(Q(i)* (2^13)));
end
fclose(fid);

%% 繪製
figure
time = 3;
subplot(time,1,1);
plot(mt);
title('基帶資料');

subplot(time,1,2);
plot(mod_data);
title('調製資料');

subplot(time,1,3);
plot(demod);
title('解調資料');

結果:

image-20241004235833600

4.FPGA解調

邏輯程式碼:

module fm_demod(
    input           clk             ,
    input           rst             ,
    //解調引數
    input           i_valid         ,
    input [15:0]    i_data_i        ,
    input [15:0]    i_data_q        ,
    output reg          o_rdy       ,
    output reg [15:0]   o_data    

);

    wire            fm_valid          ;
    wire [23:0]     fm_i              ;
    wire [23:0]     fm_q              ;

    wire            fm_rdy            ;
    wire [47 : 0]   m_axis_dout_tdata ;
    wire [15:0]     fm_phase          ;  
    //AM 解調

    assign fm_valid     = i_valid                        ;
    assign fm_i         = {{8{i_data_i[15]}},i_data_i}   ;
    assign fm_q         = {{8{i_data_q[15]}},i_data_q}   ;           
   
    cordic_translate cordic_translate (
        .aclk                     (clk                      ),                                        // input wire aclk
        .s_axis_cartesian_tvalid  (fm_valid                 ),  // input wire s_axis_cartesian_tvalid
        .s_axis_cartesian_tdata   ({fm_i,fm_q}              ),    // input wire [47 : 0] s_axis_cartesian_tdata
        .m_axis_dout_tvalid       (fm_rdy                   ),            // output wire m_axis_dout_tvalid
        .m_axis_dout_tdata        (m_axis_dout_tdata        )              // output wire [47 : 0] m_axis_dout_tdata
    );

    reg [15:0] fm_phase_d;

    assign fm_phase = m_axis_dout_tdata[24 +:16];
    always @(posedge clk)begin
        if(rst)begin
            o_rdy       <= 0;
            o_data      <= 0;
            o_data      <= 0;
        end
        else begin
            o_rdy       <= fm_rdy;
            fm_phase_d  <= fm_phase[15:0];
            o_data      <= fm_phase[15:0] - fm_phase_d;
        end
    end
        
endmodule

模擬程式碼:


module tb_fm_demod();
    reg     clk;
    reg     rst;

    initial begin
        clk <= 0;
        rst <=   1;
        #300
        rst <= 0;
    end

    always #(100/2) clk  <=~clk;
    
    reg     valid;
    reg     [15:0]  din_i;
    reg     [15:0]  din_q;
    wire          o_rdy     ;
    wire  [15:0]  o_data  ;

fm_demod   fm_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("FM.txt","r");
    end  

    reg     [15:0]  cnt;


    always @(posedge clk)begin
        if(rst)begin
            din_i   <= 0;
            din_q   <= 0;
            cnt     <= 0;
            valid   <= 0;
        end
        else if(cnt <= 1000)begin
            valid   <= 1;
            flag = $fscanf(file_rd,"%d %d",din_i,din_q);
            cnt <= cnt + 1;
        end
        else begin
            $fclose(file_rd);
            $stop();
        end
    end
endmodule

模擬結果:

FM的正交解調法

相關文章