BCH码(Bose-Chaudhuri-Hocquenghem)是汉明码的推广,能在长码字中纠正多个错误。BCH码是循环码的子类,具有丰富的代数结构,在卫星通信、存储系统和5G NR中广泛应用。
| BCH码 | n | k | t | 效率 | 应用 |
|---|---|---|---|---|---|
| BCH(7,4) | 7 | 4 | 1 | 57% | =汉明码 |
| BCH(15,5) | 15 | 5 | 3 | 33% | 教学 |
| BCH(15,7) | 15 | 7 | 2 | 47% | 教学 |
| BCH(63,51) | 63 | 51 | 2 | 81% | 卫星 |
| BCH(255,239) | 255 | 239 | 2 | 94% | 光通信 |
BCH码的构造和译码依赖于有限域GF(2^m)的运算。GF(2^4)中,本原多项式p(x)=x^4+x+1,元素alpha满足alpha^4=alpha+1。
有限域中的加法是异或运算,乘法需要对指数取模2^m-1。这些运算在硬件中通过查找表或组合逻辑实现。
BCH码的生成多项式g(x)由alpha, alpha^3, ..., alpha^(2t-1)的最小多项式的LCM构成。对于BCH(15,7,2),g(x)=m1(x)·m3(x),其中m1(x)=x^4+x+1, m3(x)=x^4+x^3+x^2+x+1。
BCH编码等价于多项式除法:将信息多项式m(x)左移n-k位后对g(x)取模,得到的余式即为校验位。硬件实现使用LFSR(线性反馈移位寄存器),每个时钟处理1位,吞吐率高。
编码过程:(1) 信息位移入LFSR的同时输出 (2) n-k个时钟后切换输出校验位
BCH译码分为4步:
对于t=2的BCH码,sigma(x)=x^2+S1·x+(S1^2+S3/S1),可以直接求解。
// bch_15_7.v - BCH(15,7,2)编码器
// 第09课:BCH码
module bch_encoder_15_7 (
input wire clk, rst_n,
input wire [6:0] data_in,
input wire valid_in,
output reg [14:0] code_out,
output reg valid_out
);
reg [7:0] shift_reg; // g(x) = x^8+x^7+x^6+x^4+1
reg [3:0] bit_cnt;
reg gate;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
shift_reg<=0; code_out<=0; valid_out<=0; bit_cnt<=0; gate<=1;
end else if (valid_in) begin
if (bit_cnt < 7) begin
gate <= 1'b1;
code_out[14-bit_cnt] <= data_in[6-bit_cnt];
shift_reg <= {shift_reg[6:0],data_in[6-bit_cnt]} ^
({8{shift_reg[7]}} & 8'b10111001);
end else if (bit_cnt < 15) begin
gate <= 1'b0;
code_out[14-bit_cnt] <= shift_reg[7];
shift_reg <= {shift_reg[6:0],1'b0};
end else begin
valid_out <= 1'b1; bit_cnt <= 0; gate <= 1;
end
bit_cnt <= bit_cnt + 1;
end else valid_out <= 0;
end
endmodule
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
def gf2_poly_mul(a, b):
result = 0
while b:
if b & 1: result ^= a
a <<= 1; b >>= 1
return result
def gf2_poly_mod(dividend, divisor):
d_bits = divisor.bit_length() - 1
while dividend.bit_length() > d_bits:
shift = dividend.bit_length() - divisor.bit_length()
dividend ^= divisor << shift
return dividend
def bch_encode(data_7bit):
g = 0b101110001
msg = data_7bit << 8
return msg ^ gf2_poly_mod(msg, g)
def simulate_bch():
np.random.seed(42); num=20000; snr_range=np.arange(0,12)
ber_u,ber_c=[],[]
for snr_db in snr_range:
bits=np.random.randint(0,2,num*7); sym=1-2*bits
ns=np.sqrt(1/(2*10**(snr_db/10)))*np.random.randn(len(sym))
ber_u.append(max(np.sum(bits!=((sym+ns)<0).astype(int))/len(bits),1e-7))
err=total=0
for _ in range(num):
d=np.random.randint(0,128); c=bch_encode(d)
sym_c=np.array([(c>>i)&1 for i in range(14,-1,-1)])
bpsk=1-2*sym_c; n=np.sqrt(1/(2*10**(snr_db/10)))*np.random.randn(15)
hard=((bpsk+n)<0).astype(int)
rx=sum(int(hard[i])<<(14-i) for i in range(15))
# Simplified: just extract data bits (no decoding for now)
dd = rx >> 8
d_bits=[(d>>i)&1 for i in range(6,-1,-1)]
dd_bits=[(dd>>i)&1 for i in range(6,-1,-1)]
err+=sum(a!=b for a,b in zip(d_bits,dd_bits)); total+=7
ber_c.append(max(err/total,1e-7))
plt.figure(figsize=(10,7))
plt.semilogy(snr_range,ber_u,'c-o',markersize=4,label='未编码')
plt.semilogy(snr_range,ber_c,'#10b981-s',markersize=4,label='BCH(15,7)')
plt.xlabel('Eb/N0(dB)'); plt.ylabel('BER')
plt.title('BCH(15,7)编码增益'); plt.legend()
plt.grid(True,alpha=0.3,which='both'); plt.ylim(1e-6,1)
plt.savefig('/var/www/ttl/digital-comm/bch_gain.png',dpi=100,facecolor='#0f172a')
print("Done!")
if __name__=='__main__':
d=0b1011011; c=bch_encode(d)
print(f"编码: {d:07b} -> {c:015b}")
simulate_bch()
BCH码的构造依赖于有限域GF(2^m)上的本原元素alpha。生成多项式g(x)由alpha^1, alpha^3, ..., alpha^(2t-1)的最小多项式确定。
对于BCH(15,7,2)码,我们需要alpha^1和alpha^3的最小多项式。
GF(2^4)基于本原多项式p(x) = x^4 + x + 1,有15个非零元素:
| 幂次 | 多项式 | 二进制 | 整数 |
|---|---|---|---|
| α⁰ | 1 | 0001 | 1 |
| α¹ | α | 0010 | 2 |
| α² | α² | 0100 | 4 |
| α³ | α³ | 1000 | 8 |
| α⁴ | α+1 | 0011 | 3 |
| α⁵ | α²+α | 0110 | 6 |
| α⁶ | α³+α² | 1100 | 12 |
| α⁷ | α³+α+1 | 1011 | 11 |
| α⁸ | α²+1 | 0101 | 5 |
| α⁹ | α³+α | 1010 | 10 |
| α¹⁰ | α²+α+1 | 0111 | 7 |
| α¹¹ | α³+α²+α | 1110 | 14 |
| α¹² | α³+α²+α+1 | 1111 | 15 |
| α¹³ | α³+α²+1 | 1101 | 13 |
| α¹⁴ | α³+1 | 1001 | 9 |
BM算法是求解错误定位多项式sigma(x)的高效算法,复杂度O(t^2)。算法迭代地增加sigma(x)的阶数,直到它能产生正确的伴随式序列。
BM算法的核心步骤:
对于t=2的BCH码,BM算法只需2次迭代,非常高效。
Chien搜索通过计算sigma(alpha^(-i))的值来判断位置i是否有错误。如果sigma(alpha^(-i))=0,则位置i有错误,需要翻转该位。
硬件实现中,Chien搜索使用移位寄存器结构,每个时钟周期测试一个位置,N个周期完成搜索。这可以与后续的错误纠正并行执行。
完整的通信系统仿真需要考虑多个因素:信道模型、编码增益、同步误差、实现损耗等。以下Python代码提供了完整的系统级仿真框架。
#!/usr/bin/env python3
# 第09课系统级仿真
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erfc
def ber_theory_bpsk(snr_db):
return 0.5 * erfc(np.sqrt(10**(snr_db/10)))
def simulate_system(mod_type='bpsk', coding_gain_db=0, num_bits=50000):
np.random.seed(42)
snr_range = np.arange(0, 20)
ber_sim = []
for snr_db in snr_range:
effective_snr = snr_db + coding_gain_db
snr_lin = 10**(effective_snr/10)
bits = np.random.randint(0, 2, num_bits)
symbols = 1 - 2*bits
noise_std = 1.0 / np.sqrt(2*snr_lin)
noise = noise_std * np.random.randn(len(symbols))
rx = symbols + noise
dec = (rx < 0).astype(int)
ber = np.sum(bits != dec) / num_bits
ber_sim.append(max(ber, 1e-7))
return snr_range, ber_sim
snr, ber_u = simulate_system('bpsk', 0)
_, ber_coded = simulate_system('bpsk', 2)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
ax1.semilogy(snr, ber_u, 'c-o', markersize=3, label='未编码')
ax1.semilogy(snr, ber_coded, '#10b981-s', markersize=3, label='编码(+2dB)')
ax1.set_xlabel('Eb/N0 (dB)'); ax1.set_ylabel('BER')
ax1.set_title('第09课:BER仿真'); ax1.legend()
ax1.grid(True, alpha=0.3, which='both'); ax1.set_ylim(1e-7, 1)
snr_range2 = np.arange(0, 25)
throughput = [(1 - ber_theory_bpsk(s)) * 1e6 for s in snr_range2]
ax2.plot(snr_range2, np.array(throughput)/1e6, '#f59e0b', linewidth=2)
ax2.set_xlabel('SNR (dB)'); ax2.set_ylabel('吞吐率 (Mbps)')
ax2.set_title('吞吐率 vs SNR'); ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('/var/www/ttl/digital-comm/lesson09_sys.png', dpi=100,
facecolor='#0f172a', edgecolor='none')
print("系统级仿真图已保存")
实际硬件实现与理论性能之间总存在差距,称为实现损耗(Implementation Loss)。主要来源:
典型总实现损耗:3-6dB。好的设计可以将损耗控制在3dB以内。
练习1:实现BCH(31,16)编码器,计算纠错能力t
练习2:实现完整的PGZ译码算法(支持纠2错)
练习3:仿真BCH码在突发错误信道下的性能,设计交织器
练习4:在Verilog中实现GF(2^4)的完整乘法器和对数表
练习5:比较BCH码和RS码在相同码率下的性能差异
你掌握了BCH码的设计与实现!
下一课预告:第10课学习RS码。