위상 변조 신호의 직교 복조 기법

위상 변조 신호의 원리

위상 변조(PM)는 정보를 반송파의 위상 변화에 저장하는 변조 방식입니다. 수학적으로 다음과 같이 표현됩니다:

\[s(t) = A \cdot \cos(\omega_c t + K_f \cdot m(t))\]

여기서:

  • \(A\): 반송파 진폭
  • \(m(t)\): 기저대역 신호
  • \(\omega_c\): 반송파 각주파수
  • \(K_f\): 변조 감도

직교 변조 표현식

PM 신호는 동상(I)과 직교(Q) 성분으로 분해할 수 있습니다:

\[ \begin{align*} I(t) &= \cos(K_f \cdot m(t)) \\ Q(t) &= \sin(K_f \cdot m(t)) \\ s(t) &= A \cdot [I(t) \cdot \cos(\omega_c t) - Q(t) \cdot \sin(\omega_c t)] \end{align*} \]

디지털 직교 복조 원리

수신된 신호에 대해 I/Q 성분을 분리합니다(\(\varphi\)는 위상 오차):

I 채널 처리

\[ I[n] = \text{LPF}\{s[n] \cdot \cos(\omega_c n + \varphi)\} = \frac{1}{2} \cos(K_f \cdot m[n] - \varphi) \]

Q 채널 처리

\[ Q[n] = \text{LPF}\{s[n] \cdot \sin(\omega_c n + \varphi)\} = \frac{1}{2} \sin(K_f \cdot m[n] - \varphi) \]

위상 복원

\[ M[n] = \arctan\left(\frac{Q[n]}{I[n]}\right) = K_f \cdot m[n] - \varphi \]

실제 구현에서는 atan2 함수를 사용해 사분면 문제를 해결합니다:

\[ M[n] = \text{atan2}(Q[n], I[n]) \]

MATLAB 시뮬레이션

sampleRate = 20000;  % 샘플링 주파수
numPoints = 1000;    % 데이터 포인트 수
baseFreq = 100;      % 기저 주파수
carrierFreq = 500;   % 반송파 주파수

time = (0:numPoints-1) / sampleRate;
baseSignal = cos(2*pi*baseFreq*time);
phaseConst = 2;
phaseOffset = pi/3;

% I/Q 신호 생성
I_comp = cos(phaseConst * baseSignal + phaseOffset);
Q_comp = sin(phaseConst * baseSignal + phaseOffset);

% 변조 신호 생성
modSignal = I_comp .* cos(2*pi*carrierFreq*time) - ...
            Q_comp .* sin(2*pi*carrierFreq*time);

% 복조 (atan2 사용)
demodPhase = atan2(Q_comp, I_comp);

% 위상 언래핑
for idx = 2:length(demodPhase)
    if demodPhase(idx) - demodPhase(idx-1) > pi
        demodPhase(idx:end) = demodPhase(idx:end) - 2*pi;
    elseif demodPhase(idx) - demodPhase(idx-1) < -pi
        demodPhase(idx:end) = demodPhase(idx:end) + 2*pi;
    end
end

% DC 오프셋 제거
dcComp = mean(demodPhase);
demodBase = demodPhase - dcComp;

FPGA 구현

하드웨어 설계

module phase_demod (
  input         clock,
  input         reset,
  input         data_valid,
  input  [15:0] i_component,
  input  [15:0] q_component,
  output        output_ready,
  output [15:0] demod_output
);

  wire        cordic_valid;
  wire [23:0] cordic_i_in;
  wire [23:0] cordic_q_in;
  wire        cordic_ready;
  wire [47:0] cordic_result;

  // 데이터 형식 확장
  assign cordic_valid = data_valid;
  assign cordic_i_in = {{8{i_component[15]}}, i_component};
  assign cordic_q_in = {{8{q_component[15]}}, q_component};

  // CORDIC 프로세서
  cordic_arctan arctan_unit (
    .clk(clock),
    .valid_in(cordic_valid),
    .x_in(cordic_i_in),
    .y_in(cordic_q_in),
    .valid_out(cordic_ready),
    .angle_out(cordic_result)
  );

  assign demod_output = cordic_result[39:24];
  assign output_ready = cordic_ready;

endmodule

테스트벤치

module demod_testbench;
  reg clk, rst;
  reg valid;
  reg [15:0] i_data, q_data;
  wire ready;
  wire [15:0] out_data;

  phase_demod demod_uut (
    .clock(clk),
    .reset(rst),
    .data_valid(valid),
    .i_component(i_data),
    .q_component(q_data),
    .output_ready(ready),
    .demod_output(out_data)
  );

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

  always #50 clk = ~clk;

  integer data_file;
  integer count;
  initial begin
    data_file = $fopen("IQ_data.txt", "r");
    count = 0;
  end

  always @(posedge clk) begin
    if (!rst && count < 1000) begin
      valid = 1;
      $fscanf(data_file, "%d %d", i_data, q_data);
      count = count + 1;
    end else if (count >= 1000) begin
      $fclose(data_file);
      $finish;
    end
  end
endmodule

태그: 위상변조 직교복조 CORDIC Matlab FPGA

7월 9일 18:00에 게시됨