▲基于QPP交织器和咬尾编码的Turbo编译码MATLAB误码率仿真

目录

✅1.引言

✅2.基于QPP交织器和咬尾编码的Turbo编译码原理

2.1 RSC编码的状态方程

2.2 QPP交织器原理

2.3 咬尾Tail-Biting机制

2.3.1 咬尾初始状态的求解

2.3.2 Max-Log-MAP译码原理

2.3.3 咬尾网格的α/β初始化

2.3.4 软判决LLR输出

✅3.MATLAB程序

✅4.仿真结果分析

✅5.完整程序下载


✅1.引言

Turbo码由并行级联卷积码(PCCC) 构成,核心是两个递归系统卷积码(RSC) 编码器通过一个交织器并联,并在译码端通过两个软输入软输出(SISO)译码器进行迭代信息交换,逼近香农极限。传统卷积码用归零(Trellis Termination) 让编码器回到零状态,但需额外发送m个尾比特,造成码率损失,短码尤为明显。咬尾码要求编码器的起始状态=结束状态,使网格首尾相连成"环",从而消除尾比特开销、保持码率,并避免边界比特保护不足的问题。

✅2.基于QPP交织器和咬尾编码的Turbo编译码原理

Turbo码由并行级联卷积码(PCCC) 构成,核心是两个递归系统卷积码(RSC) 编码器通过一个交织器并联,并在译码端通过两个软输入软输出(SISO)译码器进行迭代信息交换,逼近香农极限。

2.1 RSC编码的状态方程

本程序采用LTE标准的8状态RSC,生成多项式:

其中g0为反馈多项式(八进制13),g1为前馈多项式(八进制15)。

设寄存器状态sk=[m1,m2,m3]T,输入比特uk。由于是递归系统码,反馈输入为:

2.2 QPP交织器原理

二次置换多项式(Quadratic Permutation Polynomial, QPP) 是LTE采用的交织方案,其映射定义为:

对于K=1024,取f1=31, f2=64。QPP成为双射(无冲突排列)的充要条件是:f1与K互质,且f2的所有素因子均整除K。

其优点:

2.3 咬尾Tail-Biting机制

传统卷积码用归零(Trellis Termination) 让编码器回到零状态,但需额外发送m个尾比特,造成码率损失,短码尤为明显。咬尾码要求编码器的起始状态=结束状态,使网格首尾相连成"环",从而消除尾比特开销、保持码率,并避免边界比特保护不足的问题。

2.3.1 咬尾初始状态的求解

设循环初始状态为sc。在无外部输入贡献分离后,输入序列驱动的末状态可写为:

其中sf0是从零状态出发编码整个序列得到的末状态(即程序中第一步试编码结果)。咬尾条件要求sK=sc,代入得:

2.3.2 Max-Log-MAP译码原理

BPSK经AWGN信道后,接收符号r对应的对数似然比(LLR) 为:

网格中从状态s经输入u的分支转移度量(对数域):

其中La为来自另一译码器的先验(外)信息,p为该分支的校验比特。

标准BCJR的前向α、后向β递推涉及log⁡∑exp⁡运算。Max-Log-MAP用max⁡近似:

2.3.3 咬尾网格的α/β初始化

普通Turbo码因首尾状态已知(零态),α0和βK可确定初始化。但咬尾码的循环初始状态在译码端未知,因此本程序采用环绕(wrap-around)初始化:

初始时各状态等概(对数域置 0);

沿网格递推一遍后,将末端值αK环绕赋给α0,再迭代一遍;

β同理。

这等效于在循环网格上逼近真实的稳态初值,迭代遍数越多越精确。

2.3.4 软判决LLR输出

对每个时刻k,综合所有分支计算后验LLR:

外信息(去除内信息后传递):

译码器1的外信息经交织送给译码器2作先验,译码器2的外信息解交织反馈给译码器1,如此迭代nIter次后硬判决:

✅3.MATLAB程序

本系统的matlab核心程序如下:

%全局参数
K      = 1024;                % 信息位长度
rate   = '1/2';               
EbN0dB = 0:1:10;             % 仿真信噪比范围
maxFrm = 1000;                 % 每个SNR最大帧数
maxErr = 100;                  % 每个SNR目标错误帧
nIter  = 1;                   % Turbo迭代次数

% 构建RSC网格 (8状态)
trellis = buildTrellis();
% QPP交织器索引 (0-based -> 1-based)
[f1,f2] = qppParams(K);
piIdx = mod(f1*(0:K-1) + f2*(0:K-1).^2, K) + 1;
% A^K 用于咬尾循环状态求解
AK = gf2_AK(K);
...........................................................
figure('Color','w');
semilogy(EbN0dB, BER, '-o','LineWidth',1.8,'MarkerFaceColor','b');
grid on; 
xlabel('Eb/N0 (dB)'); 
ylabel('BER');
title(sprintf('咬尾Turbo码性能 (K=%d, 码率=%s, Max-Log-MAP)',K,rate));

if nIter == 1
   save R1.mat EbN0dB BER
end
if nIter == 2
   save R2.mat EbN0dB BER
end
if nIter == 3
   save R3.mat EbN0dB BER
end
if nIter == 10
   save R4.mat EbN0dB BER
end

figure
load R1.mat
semilogy (EbN0dB,BER,'-bs',...
   'LineWidth',1,...
   'MarkerSize',6,...
   'MarkerEdgeColor','k',...
   'MarkerFaceColor',[0.9,0.0,0.0]);
hold on
load R2.mat
semilogy (EbN0dB,BER,'-mo',...
   'LineWidth',1,...
   'MarkerSize',6,...
   'MarkerEdgeColor','k',...
   'MarkerFaceColor',[0.5,0.9,0.0]);
hold on
load R3.mat
semilogy (EbN0dB,BER,'-b^',...
   'LineWidth',1,...
   'MarkerSize',6,...
   'MarkerEdgeColor','k',...
   'MarkerFaceColor',[0.2,0.9,0.5]);
hold on
load R4.mat
semilogy (EbN0dB,BER,'-r>',...
   'LineWidth',1,...
   'MarkerSize',6,...
   'MarkerEdgeColor','k',...
   'MarkerFaceColor',[0.9,0.9,0.0]);
grid on; 
xlabel('Eb/N0 (dB)'); 
ylabel('BER');

legend('nIter = 1','nIter = 2','nIter = 3','nIter = 10');

✅4.仿真结果分析

测试结果如下:

nIter=1(蓝色方块线,性能最差)

只做1次译码迭代,没有充分利用迭代译码的置信信息迭代优化,无论高低信噪比,误码率始终是四条曲线里最高的。

即使信噪比拉到 10dB,BER 仅降到约5×10^−3,远达不到可靠通信级别。

nIter=2(绿色圆形线,性能中等)

第二次迭代修正了第一次的译码软信息,误码性能明显优于迭代1次;

随着Eb/N0升高,BER 快速下降,10dB 时误码率来到10^−5量级。

nIter=3(蓝色三角线,性能大幅提升)

迭代3次后,译码性能提升幅度非常显著:在6dB之后,误码率下降速度远快于迭代1、2次的曲线;

在8dB时BER就已经达到10^−5,只用3次迭代就实现了很高的通信可靠性。

nIter=10(红色三角线,性能最优)

迭代次数提升到10次,是四条曲线里误码性能最好的一条:

在低信噪比(0~4dB)区间,迭代3次、10次两条曲线几乎重合,低噪条件下迭代次数增益很小;

当Eb/N0>4dB后进入瀑布区(误码陡降区),迭代次数越多,误码下降越快;

8dB时迭代10次BER已经低于10^−5,是四条曲线里最低的。

posted @ 2026-06-26 00:19  hlayumi  阅读(19)  评论(0)    收藏  举报