循環碼是線性分組碼的一類重要編碼方式,以其豐富的代數結構和高效的編解碼算法廣泛應用於通訊系統。本文詳細講解如何使用 MATLAB 實現 (7,3) 循環碼的編碼過程,並透過蒙特卡洛模擬分析其在加性高斯白噪聲(AWGN)信道下的錯誤率性能。
g(x) = x⁴ + x + 1(八進制 023)或 x⁴ + x³ + 1(八進制 031)clear; clc; close all;
% (7,3) 循環碼參數
n = 7; k = 3; r = n - k;
% 生成多項式 g(x) = x^4 + x + 1 -> [1 0 0 1 1]
g = [1 0 0 1 1];
% 構造生成矩陣 G (系統碼形式 [I_k | P])
% 利用循環移位特性生成
G = zeros(k, n);
for i = 0:k-1
% 計算 x^(r+i) mod g(x) 的餘式
msg = [1, zeros(1, r+i-1)]; % x^(r+i)
[~, rem] = deconv(msg, g); % 多項式除法取餘
rem = fliplr(rem); % 係數順序調整
rem = [zeros(1, r - length(rem)), rem]; % 補齊長度
% 系統碼形式:前 k 位為單位矩陣,後 r 位為校驗位
G(i+1, :) = [zeros(1, i), 1, zeros(1, k-i-1), rem];
end
disp('生成矩陣 G:'); disp(G);
% 校驗矩陣 H = [-P^T | I_r] (GF(2) 下 -P^T = P^T)
P = G(:, k+1:n);
H = [P.', eye(r)];
disp('校驗矩陣 H:'); disp(H);
% 驗證 G * H' = 0 (mod 2)
if all(mod(G * H', 2) == 0, 'all')
disp('G*H^T = 0 驗證通過');
end
function codeword = cyclic_encode_7_3(message, G)
% 循環碼 (7,3) 編碼
% message: 1x3 或 Nx3 二進制矩陣
% 返回: 1x7 或 Nx7 碼字
message = reshape(message, [], 3);
codeword = mod(message * G, 2);
end
function decoded = cyclic_decode_7_3(received, H)
% 循環碼 (7,3) 硬判決解碼 - 綜合校驗向量查表法
% received: 1x7 或 Nx7 接收向量
% 返回: 1x3 或 Nx3 解碼資訊位
received = reshape(received, [], 7);
syndrome = mod(received * H', 2); % 綜合校驗向量
% 預計算所有單錯誤型態的綜合校驗向量
% 錯誤型態: e_i 第 i 位為 1,其餘 0
error_patterns = eye(7);
syndrome_table = mod(error_patterns * H', 2);
decoded = zeros(size(received, 1), 3);
for idx = 1:size(received, 1)
s = syndrome(idx, :);
% 查找匹配的錯誤型態
match_idx = find(all(bsxfun(@eq, syndrome_table, s), 2));
if ~isempty(match_idx)
% 糾錯
corrected = mod(received(idx, :) + error_patterns(match_idx, :), 2);
else
corrected = received(idx, :); % 無法糾正或無錯誤
end
% 取前 3 位為資訊位 (系統碼形式)
decoded(idx, :) = corrected(1:3);
end
end
% 模擬參數
EbNo_dB = 0:2:10; % Eb/No 範圍 (dB)
num_frames = 1e5; % 每個 SNR 點模擬幀數
target_errors = 100; % 目標錯誤幀數 (提前終止)
ber = zeros(size(EbNo_dB));
bler = zeros(size(EbNo_dB));
fprintf('開始蒙特卡洛模擬...\n');
for snr_idx = 1:length(EbNo_dB)
EbNo = 10^(EbNo_dB(snr_idx)/10);
% 噪聲方差: σ² = 1/(2*R*EbNo), R = k/n
R = k/n;
noise_var = 1/(2*R*EbNo);
sigma = sqrt(noise_var);
frame_errors = 0;
bit_errors = 0;
total_bits = 0;
frames = 0;
while frame_errors < target_errors && frames < num_frames
frames = frames + 1;
% 隨機生成資訊位
msg = randi([0 1], 1, k);
% 編碼
cw = cyclic_encode_7_3(msg, G);
% BPSK 調制: 0 -> +1, 1 -> -1
tx = 1 - 2*cw;
% AWGN 信道
rx = tx + sigma * randn(1, n);
% 硬判決解調: >0 -> 0, <0 -> 1
rx_hard = (rx < 0);
% 解碼
dec = cyclic_decode_7_3(rx_hard, H);
% 統計錯誤
bit_err = sum(msg ~= dec);
bit_errors = bit_errors + bit_err;
if bit_err > 0
frame_errors = frame_errors + 1;
end
total_bits = total_bits + k;
end
ber(snr_idx) = bit_errors / total_bits;
bler(snr_idx) = frame_errors / frames;
fprintf('Eb/No=%ddB: BER=%.2e, BLER=%.2e (frames=%d)\n', ...
EbNo_dB(snr_idx), ber(snr_idx), bler(snr_idx), frames);
end
% 繪製 BER 曲線
figure;
semilogy(EbNo_dB, ber, 'b-o', 'LineWidth', 1.5); hold on;
semilogy(EbNo_dB, bler, 'r-s', 'LineWidth', 1.5);
% 理論無編碼 BPSK 曲線對比
ber_uncoded = 0.5 * erfc(sqrt(10.^(EbNo_dB/10)));
semilogy(EbNo_dB, ber_uncoded, 'k--', 'LineWidth', 1);
xlabel('E_b/N_0 (dB)'); ylabel('Bit Error Rate');
legend('(7,3) 循環碼 BER', '(7,3) 循環碼 BLER', '無編碼 BPSK 理論值');
title('(7,3) 循環碼在 AWGN 信道下的性能');
grid on;
| 現象 | 可能原因 | 解決方法 |
|---|---|---|
| BER 曲線無下降趨勢 | 編碼/解碼邏輯錯誤,或雜訊方差計算錯誤 | 驗證 G*H'=0;檢查 noise_var = 1/(2*R*EbNo) |
| 模擬極慢 | 矩陣運算未向量化,逐幀循環 | 批次處理多幀;使用 GPU 加速 (Parallel Computing Toolbox) |
| 低 SNR 區 BER > 0.5 | BPSK 映射邏輯反向 | 確認 0->+1, 1->-1 映射一致性 |
vitdec、convenc 配合循環碼狀態圖cyclgen、cyclpoly、encode、decode 驗證自寫代碼完整代碼已可直接在 MATLAB R2018+ 環境運行,建議先跑通基礎流程,再根據具體需求調整模擬參數、解碼算法或信道模型。