AM 변조의 기본 원리
진폭 변조(AM) 신호는 반송파의 진폭 변화를 통해 정보를 전달합니다. 수학적 표현은 다음과 같습니다:
\[s(t) = (A + m(t)) \cdot \cos(2\pi f_t + \varphi)\]
여기서:
A: 베이스밴드 신호의 DC 성분m(t): 전송할 베이스밴드 신호cos(2πf_t + φ): 반송파 신호
직교 복조의 수학적 접근
기존 동기 복조는 반송파 주파수/위상 정확도에 취약합니다. 직교 복조는 이 문제를 해결하며, 그 과정은 다음과 같습니다:
\[
\begin{align*}
I(t) &= s(t) \cdot \cos(2\pi f_2 t + \phi) \\
Q(t) &= s(t) \cdot \sin(2\pi f_2 t + \phi)
\end{align*}
\]
삼각함수 변환 후 저대역 필터 적용:
\[
\begin{align*}
I(t) &= \frac{1}{2}(A + m(t)) \cos(2\pi f_{\Delta} t - \phi) \\
Q(t) &= -\frac{1}{2}(A + m(t)) \sin(2\pi f_{\Delta} t - \phi)
\end{align*}
\]
최종 신호 복원:
\[
s_{\text{복원}}(t) = \sqrt{I(t)^2 + Q(t)^2} = \frac{1}{2}(A + m(t))
\]
단, \(A + m(t) > 0\) 조건이 만족되어야 왜곡이 발생하지 않습니다.
DC 성분 제거 기법
평균값 필터
\[
\bar{x} = \frac{1}{N} \sum_{i=0}^{N-1} x[n-i]
\]
filter_len = [64, 128, 256];
figure;
hold on;
for n = filter_len
coeff = ones(1,n)/n;
[resp, freq] = freqz(coeff, 1, 2048, 1000);
plot(freq, abs(resp), 'DisplayName', sprintf('N=%d',n));
end
title('주파수 응답 특성');
xlabel('주파수(Hz)');
ylabel('진폭');
legend;
고역통과 필터
베이스밴드 신호 대역보다 낮은 차단주파수 설정이 핵심입니다.
MATLAB 시뮬레이션
fs = 10e6; % 샘플링 레이트
dc_level = 1; % DC 오프셋
base_freq = 0.1e6;
carrier_freq = 2e6;
t = 0:1/fs:(samples-1)/fs;
base_sig = cos(2*pi*base_freq*t);
% 변조
phase_offset = pi/3;
mod_sig = (dc_level + base_sig) .* cos(2*pi*carrier_freq*t + phase_offset);
% 복조
demod_sig = abs(hilbert(mod_sig)) - dc_level;
% 시각화
subplot(311); plot(base_sig); title('원본 신호');
subplot(312); plot(mod_sig); title('변조 신호');
subplot(313); plot(demod_sig); title('복조 신호');
FPGA 구현
하드웨어 로직
module am_demod (
input clk, rst_n,
input data_valid,
input [15:0] i_component,
input [15:0] q_component,
output demod_ready,
output [15:0] baseband_out
);
wire [23:0] ext_i = {{8{i_component[15]}}, i_component};
wire [23:0] ext_q = {{8{q_component[15]}}, q_component};
cordic_processor demod_core (
.clk(clk),
.valid_in(data_valid),
.in_data({ext_i, ext_q}),
.valid_out(demod_ready),
.out_data(cordic_out)
);
assign baseband_out = cordic_out[15:0];
endmodule
테스트벤치
module tb_am_demod;
reg clk, reset;
reg [15:0] i_in, q_in;
am_demod uut (
.clk(clk),
.rst_n(~reset),
.data_valid(1'b1),
.i_component(i_in),
.q_component(q_in)
);
initial begin
integer data_file = $fopen("am_data.txt", "r");
while (!$feof(data_file)) begin
@(posedge clk);
$fscanf(data_file, "%d %d", i_in, q_in);
end
$fclose(data_file);
$finish;
end
endmodule