1 前言
前一节所写的文章信道编码-Hamming码中,我们说到线性分组码是一类重要的纠错码,应用很广泛,其中Hamming 码、循环码、BCH 码和 RS 码都可以看作线性分组码的特例。接下来,在简要谈谈剩下的三种编码,其中重点介绍下RS编码。
2 线性分组码
2.1 循环码
循环码(Cyclic Code)是一类重要的线性分组码,它除了具有线性码的一般性质外,还具有循环性,即循环码许用码组集合中任一码字循环移位所得的码字仍为该码组集合中的一个码字。循环码的两个最引人注目的特点是:
(1)可以用反馈线性移位寄存器很容易地实现其编码和伴随式计算。
(2)由于循环码有许多固有的代数结构,从而可以找到各种简单实用的译码方法。
MATLAB提供的用来进行循环编码的函数是cyclpoly和cycgen。在使用时首先需要使用ccyclpoly生成循环码的生成多项式,然后再用cycgen生成循环码的生成矩阵和校验矩阵。
pol=cyclpoly(n,k)
pol=cyclpoly(n,k)用来生成(n,k)循环码的生成多项式。
[h,g]=cyclgen(n,pol)
[h,g]=cyclgen(n,pol)用pol生成多项式生成循环码的生成矩阵g和校验矩阵h。
2.3 BCH码
BCH(Bose-Chaudhuri-Hocquenghem,BCH)码是循环码中的一个大类,它可以是二进制码,也可以是非二进制码。二进制 BCH码的构造可具有下列参数,即:
n
=
2
m
−
1
(1)
n=2^m-1\tag{1}
n=2m−1(1)
n
−
k
≤
2
m
−
1
(2)
n-k \leq 2^m-1\tag{2}
n−k≤2m−1(2)
d
m
i
n
=
2
t
+
1
(3)
d_{min}=2t+1\tag{3}
dmin=2t+1(3)
式中,
m
(
m
≥
3
)
m(m≥3)
m(m≥3)和
t
t
t是任意正整数。这类二进制BCH码为通信系统设计者们在码长和码率方面提供了很大的选择余地。非二进制 BCH码包括非常有用的里德一索罗门(Reed-Solomon,RS)码,该码将在2.4小节介绍。
MATLAB 提供的与 BCH编码解码相关的函数是bchgenpoly、bchenc和bchdec。
[genpoly,t]= bchgenpoly(n,k)
[genpoly,t]= bchgenpoly(n,k)用来生成 ( n , k ) (n,k) (n,k) BCH 码的生成多项式 genploy 及纠错能力 t t t。
code=bchenc(msg,n,k)
code=bchenc(msg,n,k)将消息 msg 以 ( n , k ) (n,k) (n,k)的 BCH 码结构进行编码,其中 msg 是一个二进制 Galois数组。msg 的每行代表一个消息字。
decoded=bchdec(code,n,k)
decoded=bchdec(code,n,k)用来对 BCH 编码的码字进行译码。
2.4 RS码
RS码是一类具有很强纠错能力的多进制 BCH码,首先由里德(Reed)和索罗门(Solomon)提出,故称为RS码。在线性分组码中,它的纠错能力和编码效率是最高的、相比其他线性分组码而言,在同样的编码效率下,RS码的纠错能力是特别强的,特别是在短的中等码长下,其性能接近于理论值,它不但可以纠正随机错误、突发错误及两者的结合,而且来构造其他码类,如级联码。因此,RS码被广泛运用到各种通信系统中、例如,日本的BEST纠错码是(272,190)大数逻辑码,可以纠正8个错误比特,编码效率是69%;如果称用GF(
2
6
2^6
26)域上的RS(224,200)码则可以纠正12个比特的错误,编码效率可达 89%。
RS(n,k)码可以由
m
、
n
和
k
m、n和k
m、n和k,3个参数表示,其中
m
m
m表示码元符号取自域 GF(
2
n
2^n
2n),
n
n
n为码字长度,
k
k
k为信息段长度。对于一个可以纠正
t
t
t个符号错误的RS码,有如下参数:
(1)码字长度:
n
=
2
m
−
1
n=2^m-1
n=2m−1 个符号或
m
(
2
m
−
1
)
m(2^m-1)
m(2m−1)个比特。
(2)信息段:
k
(
k
=
1
,
2
,
…
,
n
−
1
)
k(k=1,2,…,n-1)
k(k=1,2,…,n−1) 个符号或
k
m
km
km个比特。
(3)监督位:
2
t
=
n
−
k
2t=n-k
2t=n−k 个符号或
2
m
t
=
m
(
n
−
k
)
2mt=m(n-k)
2mt=m(n−k)个比特。
(4)最小码距:
d
m
i
n
=
2
t
+
1
d_{min}=2t+1
dmin=2t+1个符号,或
m
d
m
i
n
=
m
(
2
t
+
1
)
md_{min}=m(2t+1)
mdmin=m(2t+1)比特。
例如,对RS(204,188)码来说,源数据被分割为188个符号一组,经过编码变换后成为204个符号长度的码字。长度为16个符号的监督位可以保证纠正码字中出现的最多8个符号错误。
RS 码的基本思想就是选择一个合适的生成多项式
g
(
x
)
g(x)
g(x),并且使得对每个信息段计算得到的码字多项式都是
g
(
x
)
g(x)
g(x)的倍式,即使得码字多项式除以
g
(
x
)
g(x)
g(x)的余式为0。这样,如果接到的码字多项式除以
g
(
x
)
g(x)
g(x)的余式不是0,则可以知道接收的码字中存在错误;而且通过进步的计算可以纠正最多
t
=
(
n
−
k
)
/
2
t=(n-k)/2
t=(n−k)/2个错误。
RS 码生成多项式一般按如下公式选择,即:
g
(
x
)
=
(
x
−
a
)
(
x
−
a
2
)
⋯
(
x
−
a
2
t
)
=
∏
i
=
1
2
t
(
x
−
a
i
)
(4)
g\left(x\right)=\left(x-a\right)\left(x-a^{2}\right)\cdots\left(x-a^{2t}\right)\\=\prod_{i=1}^{2t}\left(x-a^{i}\right) \tag{4}
g(x)=(x−a)(x−a2)⋯(x−a2t)=i=1∏2t(x−ai)(4)
式中,
a
i
a^i
ai是 GF
(
2
m
)
(2^m)
(2m)中的一个元素。如果用
d
(
x
)
d(x)
d(x)表示信息段多项式,则可以按如下方式构造码字多项式
c
(
x
)
c(x)
c(x)。首先计算商式
h
(
x
)
h(x)
h(x)和余式
r
(
x
)
r(x)
r(x),得
x
n
−
k
d
(
x
)
/
g
(
x
)
=
h
(
x
)
g
(
x
)
+
r
(
x
)
(5)
x^{n-k}d(x)/g\left(x\right)=h\left(x\right)g\left(x\right)+r\left(x\right)\tag{5}
xn−kd(x)/g(x)=h(x)g(x)+r(x)(5)
取余式
r
(
x
)
r(x)
r(x)作为校验字,然后令
c
(
x
)
=
x
n
−
k
d
(
x
)
+
r
(
x
)
(6)
c(x)=x^{n-k}d\left(x\right)+r\left(x\right)\tag{6}
c(x)=xn−kd(x)+r(x)(6)
即将信息位放置于码字的前半部分,监督位放置于码字的后半部分,则
c
(
x
)
/
g
(
x
)
=
x
n
−
k
d
(
x
)
/
g
(
x
)
+
r
(
x
)
/
g
(
x
)
=
h
(
x
)
g
(
x
)
+
r
(
x
)
+
r
(
x
)
=
h
(
x
)
g
(
x
)
(7)
\begin{aligned} c\left(x\right)/g\left(x\right) & =x^{n-k}d\left(x\right)/g\left(x\right)+r\left(x\right)/g\left(x\right) \\ & =h\left(x\right)g\left(x\right)+r\left(x\right)+r\left(x\right)\\ & =h\left(x\right)g\left(x\right) \end{aligned}\tag{7}
c(x)/g(x)=xn−kd(x)/g(x)+r(x)/g(x)=h(x)g(x)+r(x)+r(x)=h(x)g(x)(7)
因此,码字多项式
c
(
x
)
c(x)
c(x)必可被生成多项式
g
(
x
)
g(x)
g(x)整除。如果在接收端检测到余式不为0则可判断接收到的码字有错误。由于这种RS码能够纠正
t
t
t个
m
m
m进制的错误码字,所以,RS码特别适用于有突发错误的信道。
以RS(7,3)码为例介绍一下RS 码的编码过程。RS(7,3)码利用 3 个信息符号得到长度为 7 的编码,码元符号取自域,GF(
2
3
2^3
23),即
m
=
3
m=3
m=3。域GF(
2
3
2^3
23)的本原多项式为
a
3
+
a
+
1
a^3+a+1
a3+a+1,RS码的生成多项式为g(x)=
x
4
+
3
x
3
+
x
2
+
2
x
+
3
x^{4}+3x ^{3}+x^2+2x+3
x4+3x3+x2+2x+3。假设输入符号为[4 0 6],则信息段多项式
d
(
x
)
=
4
x
2
+
6
d(x)=4x^2+6
d(x)=4x2+6。生成码字的过程如下:
(1)由于码元符号取自域 GF(
2
3
2^3
23),所以一个符号可以由3个比特表示,
x
4
d
(
x
)
x^4d(x)
x4d(x)的二进制比特表示为[100 000 110 000 000 000 000]:
(2)
g
(
x
)
g(x)
g(x)的二进制比特表示为[001011001010011];
(3)计算
x
n
−
k
−
d
(
x
)
/
g
(
x
)
x^{n-k}-d(x)/g(x)
xn−k−d(x)/g(x)得的余式
r
(
x
)
r(x)
r(x)的二进制比特表示为[100 010 010 000],因此,校验位为[4 2 2 0];
(4)生成的码字即为[4 0 6 4 2 2 0]。
MATLAB 提供了RS码的编码函数rsenc和译码函数rsdec。
code = rsenc(msg,n,k)
code = rsenc(msg,n,k)将消息以 ( n , k ) (n,k) (n,k)的 RS 码结构进行编码,其中 msg 是一个 Galois 数组的符号,每个符号都有 m m m个比特。msg的每行代表一个消息字。
code =rsenc(msg,n,k,genpoly)
code =rsenc(msg,n,k,genpoly)除了参数,genpoly,该函数的使用与上面的一样。参数genpoly 用于指定 RS 码的生成多项式,以 Galois 的行矢量形式给出系数。
decoded=rsdec(code,n,k)、decoded = rsdec(code,n,k,genpoly)
decoded=rsdec(code,n,k)、decoded = rsdec(code,n,k,genpoly)它们分别对应于上面两个编码函数的译码,其参数与RS码函数一致。
例2.1 使用MATLAB函数仿真通过(15,11)RS编码和未编码情况下通过AWGN信道后的性能。假设每个符号的比特数是4,调制方式采用BPSK调制。
%% ——Author:闲鱼/b站-【不喜欢MIMO】——
clear; clc; close;
m = 4; % 每个信息符号包含的比特数
n = 15; % 码字长度
k = 11; % 码字中的信息符号数
t = (n - k) / 2; % 码的纠错能力
N = 2000; % 信息符号的行数
M = 2; % BPSK调制的阶数
SNR_dB = 0:8; % 信噪比范围 (dB)
ser = zeros(size(SNR_dB)); % 未编码误码率
ser1 = zeros(size(SNR_dB)); % 编码后误码率
% ber=berawgn(SNR_dB,'qam',16); %16-QAM理论误比特率
% SNR 循环
for i = 1:length(SNR_dB)
% 信噪比线性值
SNR = 10^(SNR_dB(i) / 10);
% pe=ber(i);
% 未编码
data_bits_uncoded = randi([0 1], N, k); % 生成随机比特
% BPSK调制
data_symbols_uncoded = pskmod(data_bits_uncoded, M);
% 添加噪声
rx_symbols_uncoded = awgn(data_symbols_uncoded, SNR_dB(i), 'measured');
% 解调
demod_bits_uncoded = pskdemod(rx_symbols_uncoded, M);
% 误码率计算
[~, ser(i)] = symerr(data_bits_uncoded, demod_bits_uncoded);
% RS 编码
msg1 = gf(data_bits_uncoded, m);
msg1 = rsenc(msg1, n, k).'; % (15,11)RS编码
msg3 = de2bi(double(msg1.x), 'left-msb'); % 转换为二进制
% BPSK调制
msg4=pskmod(msg3,M);
% y=bsc(msg3,pe);
% 添加噪声
y = awgn(double(msg4), SNR_dB(i), 'measured'); % 通过AWGN信道
% BPSK解调
y1=pskdemod(y,M);
% 硬判决
y_hard = double(y1 > 0.5); % 阈值为 0.5,硬判决为 0 或 1
% 转换为十进制
y_dec = bi2de(y_hard, 'left-msb'); % 转换为十进制
y_reshaped = reshape(y_dec, n, N).'; % 重新整理形状
% RS 解码
dec_x = rsdec(gf(y_reshaped, m), n, k); % RS 解码
% 误码率计算
[~, ser1(i)] = symerr(data_bits_uncoded, double(dec_x.x));
end
% 绘图
semilogy(SNR_dB, ser, '-ko', 'LineWidth', 0.75, 'DisplayName', '未编码');
hold on;
semilogy(SNR_dB, ser1, '-k*', 'LineWidth', 0.75, 'DisplayName', 'RS编码');
grid on;
xlabel('信噪比 (dB)');
ylabel('误码率');
legend('show');
title('RS(15,11)编码与未编码的误码率比较');
从仿真结果可以看出,在信噪比较低时(< 3.5dB),不编码的误比特率要好于编码的误比特率,这是因为编码虽然可以带来编码增益,但在传输总能量不变的情况下,由于传每个编码码字中的比特能量减少,信噪比降低,由于信噪比降低而使误码率升高,而此时码增益很小,因此,编码结果反而不如不编码的结果。而在信噪比较高时,编码增益要大于信噪比降低而导致的性能损失,因此,在信噪比(>3.5dB)时,编码结果要优于不编码的结果。
tips:最后代码还有可以改善的地方,有兴趣的同学可以更进一步完善和改进,需要更多源码的小伙伴也可以来看看我的闲鱼和b站~