一、原理
Turbo的编码器由两个并行的分量编码器组成。分量编码器的选择一般是卷积码。在Turbo码中,输入序列在进入第二个编码器时须经过一个交织器 ,用于将序列打乱。两个编码器的输出共同作为冗余信息添加到信息序列之后,对抗信道引起的错误。
- turbo编码器的结构
二、交织器
什么是交织器?
编码器中交织器的使用是实现Turbo码近似随机编码的关键。交织器实际上是一个一对一的映射函数,作用是将输入信息序列中的比特位置进行重置,以减小分量编码器输出校验序列的相关性(减小两个RSC编码器输入序列的相关性,使二者编码过程趋于独立)并且提高码重(码字中1的数目)。
如何实现交织器?
k:信息块的长度,取k = 960
s:原始数据序号,1~k
k = k1 * k2 = 4 * 240
Π(s):交织后的数据序号
根据下图所示流程,即可得到交织后的数据序号。
三、RSC 递归系统卷积码
所谓卷积码,即输出为输入和一段已知序列的卷积。
每个输入会产生三个输出。输出是输入数据和三个寄存器的值之间的模2加法。当第一个数据做完模2加法后,产生第1组输出,然后将第1个数据移入移位寄存器,作为移位寄存器新的初始值。第二个输入数据进来之后,同样进行模2运算,产生第2组输出。即先算输出,再进行移位。
-
RSC编码器结构
-
生成多项式
四、归零处理
在数据序列编码完成后,归零处理使分量编码器RSC中的移位寄存器恢复成编码前的零状态,从而使编译码变得简单易于控制。
Turbo码的归零处理如下:
(1)输入所有的编码序列,完成编码
(2)分量码开关切换,各个寄存器中的遗留状态值和反馈结构生成某些编码序列的尾部比特,这些尾比特与自身异或,使新进入寄存器的值为0。
(3)该过程直到所有移位寄存器中值全部为0。如寄存器有m个,则经过m次后寄存器将全为0。
- 实际操作
前k个时钟,开关位于a,信息被输入到编码器中。
在k个时钟之后的6个时钟,开关位于位置b。在这6个时钟的前3个时钟里,只有RSC1输出。在这6个时钟的后3个时钟里,只有RSC2输出。
所以,终止序列是(X、Y0、Y1、X’、Y0’、Y1’);
五、数据打孔(删余)
现代通信系统中,为了实现高速数据传输,系统对频带利用率要求较高,一般Turbo码的码率只有1/3,所以,频带利用率不高,为了解决这一问题,在编码器中加入了删余处理。
删余处理的具体操作即在编码完成后,将分量码输出的两路校验信息输入删余器,按照一定的规则删除一部分校验信息,减小信息的冗余度,从而提高编码效率。删余处理根据各系统自定。
在上表中,0表示删除这个数据,1表示保留这个数据。
注意,终止部分(尾比特)的穿刺表与前面数据的穿刺表不一定相同。
六、matlab程序
% 函数功能:turbo编码
% 输入:turbo_in
% 输出:turbo_out
% 时钟:clk
% rsc寄存器:reg1-->reg2-->reg3
% 移位寄存器输入:sr_in
function turbo_out=turbo(turbo_in)
% rsc参数
g1 = [1 1 1 1]; % y1的生成多项式
g0 = [1 0 1 1]; % y0的生成多项式
g = [1 1 0 1]; % rsc的生成多项式
% 数据打孔参数
punc_para = [[1 0 1 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 1]];
% 数据交织
turbo_in1 = interleaver(turbo_in);
% 初始化
rsc1_reg1 = 0;
rsc1_reg2 = 0;
rsc1_reg3 = 0;
rsc1_sr_in = mod(turbo_in(1)+rsc1_reg2+rsc1_reg3,2);
rsc2_reg1 = 0;
rsc2_reg2 = 0;
rsc2_reg3 = 0;
rsc2_sr_in = mod(turbo_in1(1)+rsc2_reg2+rsc2_reg3,2);
ram = [];
rsc1_reg = [0 0 0];
rsc2_reg = [0 0 0];
% 前k个时钟,开关位于a
for clk = 1:length(turbo_in)
% 因为先计算输出,再进行移位
% 所以注意组合逻辑放在前面,时序逻辑放在后面,对移位寄存器的赋值注意先后顺序
% rsc1
rsc1_sr_in = mod(turbo_in(clk)+rsc1_reg2+rsc1_reg3,2);
rsc1_x = turbo_in(clk);
rsc1_y0 = mod(rsc1_sr_in+rsc1_reg1+rsc1_reg3,2);
rsc1_y1 = mod(rsc1_sr_in+rsc1_reg1+rsc1_reg2+rsc1_reg3,2);
rsc1_reg3 = rsc1_reg2;
rsc1_reg2 = rsc1_reg1;
rsc1_reg1 = rsc1_sr_in;
% rsc2
rsc2_sr_in = mod(turbo_in1(clk)+rsc2_reg2+rsc2_reg3,2);
rsc2_x = turbo_in1(clk);
rsc2_y0 = mod(rsc2_sr_in+rsc2_reg1+rsc2_reg3,2);
rsc2_y1 = mod(rsc2_sr_in+rsc2_reg1+rsc2_reg2+rsc2_reg3,2);
rsc2_reg3 = rsc2_reg2;
rsc2_reg2 = rsc2_reg1;
rsc2_reg1 = rsc2_sr_in;
% 并转串
ram = [ram rsc1_x rsc1_y0 rsc1_y1 rsc2_x rsc2_y0 rsc2_y1];
rsc1_reg = [rsc1_reg;rsc1_reg3 rsc1_reg2 rsc1_reg1];
rsc2_reg = [rsc2_reg;rsc2_reg3 rsc2_reg2 rsc2_reg1];
end
% 后6个时钟,开关位于b
rsc1_sr_in = 0;
rsc2_sr_in = 0;
for clk = 1:6
% rsc1
rsc1_x = mod(rsc1_reg2+rsc1_reg3,2);
rsc1_y0 = mod(rsc1_sr_in+rsc1_reg1+rsc1_reg3,2);
rsc1_y1 = mod(rsc1_sr_in+rsc1_reg1+rsc1_reg2+rsc1_reg3,2);
rsc1_reg3 = rsc1_reg2;
rsc1_reg2 = rsc1_reg1;
rsc1_reg1 = rsc1_sr_in;
% rsc2
rsc2_x = mod(rsc2_reg2+rsc2_reg3,2);
rsc2_y0 = mod(rsc2_sr_in+rsc2_reg1+rsc2_reg3,2);
rsc2_y1 = mod(rsc2_sr_in+rsc2_reg1+rsc2_reg2+rsc2_reg3,2);
rsc2_reg3 = rsc2_reg2;
rsc2_reg2 = rsc2_reg1;
rsc2_reg1 = rsc2_sr_in;
% 并转串
ram = [ram rsc1_x rsc1_y0 rsc1_y1 rsc2_x rsc2_y0 rsc2_y1];
rsc1_reg = [rsc1_reg;rsc1_reg3 rsc1_reg2 rsc1_reg1];
rsc2_reg = [rsc2_reg;rsc2_reg3 rsc2_reg2 rsc2_reg1];
end
rsc1_x_ram = ram(1:6:length(ram));
rsc1_y0_ram = ram(2:6:length(ram));
rsc1_y1_ram = ram(3:6:length(ram));
rsc2_x_ram = ram(4:6:length(ram));
rsc2_y0_ram = ram(5:6:length(ram));
rsc2_y1_ram = ram(6:6:length(ram));
% 数据打孔
punc = repmat(punc_para,1,ceil(length(ram)/36));
punc = punc(1:length(ram));
punc_addr = find(punc);
turbo_out = ram(punc_addr);