ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

8PSK系统中Hamming与RS编码的Matlab仿真:编码增益实测与误码率对比

8PSK系统中Hamming与RS编码的Matlab仿真:编码增益实测与误码率对比 先交代一下背景我一直觉得“信道编码在高阶调制系统里到底能带来多少增益”这个问题特别值得动手验证一遍。8PSK这种每符号3比特的调制方式频谱效率确实诱人但星座点挤在一起之后抗噪声能力明显下降。于是我把Hamming码和Reed-Solomon码分别作为块编码器补进一条完整的8PSK数字信号传输链路里用Matlab完整跑通了“编码—调制—AWGN信道—解调—译码—误码统计”的全流程仿真。这篇文章把整个工程的设计思路、Matlab实现细节、误码率结果和踩坑记录都梳理一遍对通信专业的学生、做调制解调算法验证的工程师还有想快速搭一套信道编码仿真框架的人都有参考价值。1. 为什么8PSK链路需要Hamming和RS这样的块编码1.1 8PSK频谱效率换来的是什么8PSK把8个相位状态映射到3个比特上和QPSK相比相同符号速率下比特速率提升了50%。但所有数字调制的本质规律都绕不开一个权衡星座点越密点与点之间的欧氏距离越短抗噪声能力越差。以单位圆上的星座点来算QPSK相邻两个符号的距离是√2乘以信号幅度大约1.414倍幅度8PSK相邻两个符号的距离是2·sin(π/8)大约0.765倍幅度。也就是说8PSK的星座点间距只有QPSK的54%左右。要在同样的误码率目标下工作8PSK需要明显更高的信噪比。这个差距不是靠加一点发射功率就能轻松弥补的尤其在实际系统的功率和频带都受限时就需要引入信道编码来换取性能。这里可以给出一组典型对比调制方式每符号比特数星座点间距归一化达到10^-4误码所需的近似Eb/N0BPSK/QPSK1/21.414/0.707约8.4dB8PSK30.765约12dB以上所以在8PSK这种高阶调制后面补上一道信道编码是用频带冗余换取功率效率的经典思路。1.2 Hamming与RS两种“块编码”的互补定位Hamming码是线性分组码的代表Hamming(7,4)用3个校验比特保护4个信息比特可以在一个码字里纠1个比特错误同时能检测部分2比特错误。它结构简单、编解码延迟小适合处理信道中随机散布的单比特错误。Reed-Solomon码则是符号级的编码。它在伽罗华域GF(2^m)上工作一个符号由m个比特组成编码纠错都以符号为单位。RS(7,3)能纠正2个错误符号也就是说当某个符号内的多个比特同时被破坏时只算一个符号错误这对突发干扰造成的连续比特错误特别有效。在8PSK链路里硬判决解调后一个符号判决错误往往造成1到2个比特错误。单独使用Hamming(7,4)面对这类错误时纠错能力可能不够单独使用RS码则对随机分散的单比特错误有些“大材小用”。所以这个工程把两者都补充进系统里对比分析也允许配置成级联模式让两种码的优势互补。2. 系统仿真框架从发射端到接收端的完整链路2.1 整体信号流这个工程的核心链路分成三种可配置方案无编码的8PSK传输作为基准对比。仅Hamming(7,4)编码的8PSK传输。仅RS(7,3)编码的8PSK传输。可选Hamming和RS级联后的8PSK传输。发射端按照方案选择先对随机二进制比特流做块编码编码输出按每3比特一组映射成8PSK符号并调制到复数基带信号上信号进入AWGN信道叠加噪声接收端先做星座点最小距离判决解调出符号索引再按编码方案做译码最后把译码结果和原始信息比特对比统计误码率。这里有一个很重要的设计决策仿真时必须在Eb/N0每信息比特信噪比维度上对齐而不是简单地在波形信噪比SNR上对齐。因为编码引入了冗余相同符号能量下信息比特的等效信噪比会被“摊薄”曲线对比才会公平。2.2 帧结构与参数设置为了保证误码率统计可靠需要设计合适的帧结构。这个工程里采用如下参数信息比特组每次生成若干个完整的编码块。Hamming(7,4)4个信息比特编成7个码字比特。RS(7,3)3个GF(8)符号编成7个符号每个符号3比特等效处理21个信道比特中的9个信息比特。8PSK调制每符号承载3个信道比特。如果把Hamming和RS级联则RS编码输出再进行Hamming编码总码率约为(4/7)×(3/7)冗余非常大。所以工程默认模式下把它们作为独立方案对比级联模式仅用于教学演示。每信噪比点的仿真帧数建议不少于500帧每帧至少包含约1000个信息比特这样在BER10^-4附近还能统计到足够数量的错误比特。如果目标误码率更低就要相应增加帧数。2.3 仿真条件与AWGN噪声注入仿真覆盖Eb/N0从0dB到14dB的区间步长1dB。AWGN噪声注入有两种做法一是用awgn函数二是我更推荐的手动方式% 手动静默加噪声便于精确控制信噪比 snr_ebn0 EbN0_dB; % 输入Eb/N0 Rc k/n; % 编码码率 snr snr_ebn0 10*log10(Rc) 10*log10(log2(M)); % 符号SNR noise_power 10^(-snr/10); rx tx sqrt(noise_power/2) * (randn(size(tx)) 1j*randn(size(tx)));这样操作的好处是信噪比的定义完全透明不会因为awgn函数内部对信号功率的测量方式不同而出现曲线偏移。3. Hamming(7,4)编解码的Matlab实现与纠错边界3.1 线性分组码的核心生成矩阵与校验矩阵Hamming(7,4)是典型的(7,4)线性分组码。信息向量m是4比特码字c是7比特编码过程就是一个矩阵乘法c m·G。生成矩阵G由单位阵I4和一个3×4的校验子矩阵P拼接而成。这个工程采用的G和H矩阵如下% Hamming(7,4)生成矩阵 G [I4 | P] G [1 0 0 0 1 1 0; 0 1 0 0 1 0 1; 0 0 1 0 0 1 1; 0 0 0 1 1 1 1]; % 一致校验矩阵 H [P | I3] H [1 1 0 1 1 0 0; 1 0 1 1 0 1 0; 0 1 1 1 0 0 1];编码很简单。接收端拿到码字向量r后计算伴随式s mod(r * H, 2)。如果s是零向量说明没有发生可检测的错误如果s非零依据s的值可以在H的列中找到对应出错位置。3.2 编码与伴随式纠错的代码实现编码函数直接按矩阵乘法写就行function codeword hamming_encode(msg) G [1 0 0 0 1 1 0; 0 1 0 0 1 0 1; 0 0 1 0 0 1 1; 0 0 0 1 1 1 1]; codeword mod(double(msg) * G, 2); end解码函数稍微复杂一些需要计算伴随式并定位错误位置function msg_hat hamming_decode(rx_bits) H [1 1 0 1 1 0 0; 1 0 1 1 0 1 0; 0 1 1 1 0 0 1]; r double(rx_bits(:)); syndrome mod(r * H, 2); if any(syndrome) 0 corrected r; else % 在H的列中寻找与之匹配的错误模式 [~, err_pos] ismember(syndrome, H, rows); if err_pos 0 corrected r; corrected(err_pos) mod(corrected(err_pos) 1, 2); else % 出现无法判定位置的错误保留原样 corrected r; end end msg_hat corrected(1:4); % 取信息位 end这里有一个容易被忽略的细节Matlab中ismember对行的匹配非常方便但它要求二进制向量顺序完全一致。如果H的列向量没有覆盖所有可能的非零伴随式err_pos就会是0此时按“无法纠错”处理比强行纠错更稳妥。3.3 单比特纠错的边界效应Hamming(7,4)的纠错能力上限是1比特错误。如果码字里实际发生了2比特错误伴随式可能恰好指向某列的对应位置导致接收端误以为第3个位置出错反而“越纠越错”。在8PSK硬判决解调产生的错误模式中一个符号判错时相邻两个比特同时错是常有的。Hamming(7,4)面对这种错误时性能提升有限甚至可能出现负增益。所以单独使用Hamming时要把期望值放低它更适合用来说明分组码的原理以及对比验证“弱编码在强噪声下并不总是有效”这一结论。4. Reed-Solomon编解码在GF(2^m)上处理符号级突发错误4.1 从比特到符号RS的基本思想Reed-Solomon码和Hamming码本质区别在于运算单位。Hamming码在一个比特一个比特地做线性组合而RS是在GF(2^m)上做多项式运算。一个符号由m个比特组成工程里选m3即GF(8)对应8PSK每符号3比特的结构两者配合十分自然。RS(7,3)的码长n2^3-17个符号其中正文符号数k3校验符号数n-k4因此纠错能力t(n-k)/22个符号。这意味着它最多可以纠正2个符号错不管这2个符号内部错了几个比特。RS码对突发错误天然友好的原因就在这里一个符号内部的多个连续比特被噪声毁掉在RS看来只是1个符号错误纠错成本低。这在衰落信道中特别可贵因为衰落干扰往往造成连续一段时间内的符号全部出错。4.2 生成多项式与系统码编码RS编码是系统码码字前k个符号就是原始信息符号后面紧跟校验符号。校验符号由信息多项式乘以生成多项式得到。生成多项式都是根在GF(2^m)中的多项式g(x) (x - α^1)(x - α^2)(x - α^3)(x - α^4)其中α是GF(8)的本原元。展开后得到最高次数4的多项式每次编码都是多项式除法求余。在Matlab中如果只是做仿真验证最直接的方式是用Communications Toolbox的rsenc和rsdec% RS(7,3)编码 n 7; k 3; m 3; msg randi([0, 7], 1, k); % 生成3个GF(8)符号 msg_gf gf(msg, m); code_gf rsenc(msg_gf, n, k);如果不想依赖工具箱也可以手写GF(8)的查表乘法和多项式除法我建议至少实现一次“乘法表除法求余”这样才能真正理解RS编码的原理而不是只调用黑盒函数。4.3 译码伴随式、BM迭代与错误值计算RS译码的核心流程分四步由接收码字计算伴随式S_ii1到4。如果全部为0说明码字无错。由伴随式求解错误位置多项式σ(x)。常用Berlekamp-Massey迭代算法也可以在错误数t比较小时直接解线性方程。用Chien搜索逐符号地寻找σ(x)的根根的对数就是错误位置。用Forney公式计算错误值把错误值叠加回接收符号上完成纠正。在Matlab里手写完整的RS译码器篇幅不短但可以给出一个精简版的思想演示function msg_hat rs_decode_wrapper(rx_gf, n, k) % 借助工具箱的rsdec演示译码流程 decoded rsdec(rx_gf, n, k); msg_hat decoded.x; % 提取信息符号 end实际工程级实现时我更推荐用comm.RSEncoder和comm.RSDecoder系统对象它们支持向量化批量处理跑整套蒙特卡洛误码仿真时速度会快很多。4.4 RS参数选择心得选定RS参数要看具体误码场景。下面表格对比了几种常见配置RS参数符号位数m码长n信息符号k可纠符号数t码率RS(7,3)37320.429RS(7,5)37510.714RS(15,11)4151120.733RS(15,9)415930.600在8PSK系统里如果信道是纯AWGN单个8PSK符号错误大部分是单符号错误RS(7,3)的纠2符号能力有些冗余。但一旦链路里有突发干扰或者频率选择性衰落t2的优势就显现出来了。这时可以考虑交织器把连续突发错误分散到不同RS码字中让每个码字只承担少量错误符号RS的纠错能力能被充分利用。5. 8PSK调制映射与AWGN下的解调判决5.1 Gray映射的星座表8PSK的8个星座点等间隔分布在单位圆上相位为0、π/4、π/2、3π/4、π、5π/4、3π/2、7π/4。选Gray映射可以让相邻相位的星座点只差1个比特这样即使噪声导致符号判决到相邻点上误码也大多只是1个比特错误而不是把所有3个比特全打乱。这对后级译码非常重要。这个工程用的一张Gray映射表如下3比特数据星座点索引相位00000001145°011290°0103135°1104180°1115225°1016270°1007315°可以看到相邻相位索引对应的3比特数据都只有1位差异。这种“数据比特—星座点索引”的映射关系和Matlab内置pskmod的默认顺序不一定一致所以工程里用自定义映射来实现确保可复现性。5.2 手动映射与pskmod实现方式工程里我倾向于手动完成映射便于理解和扩展M 8; gray_map [0 1 3 2 6 7 5 4]; % 数据比特到星座点索引的映射 const exp(1j * 2 * pi * (0:M-1) / M); % 8个星座点 % 每3个信道比特转成8PSK符号索引 symbol_idx gray_map(bi2de(reshape(channel_bits, 3, [])., left-msb) 1) 1; tx const(symbol_idx);这里bi2de把3比特转成十进制数再通过gray_map转成星座点索引。值得注意的是gray_map下标从1开始而星座点本身用const的下标1到8表示和相位从0开始不同这个细节非常容易出bug。如果使用pskmod可以这样data_symbols bi2de(reshape(channel_bits, 3, [])., left-msb); tx pskmod(data_symbols, M, 0, gray);但不同Matlab版本对pskmod的Gray映射顺序有细微差别强烈建议在跑全链路仿真之前先打印一遍映射表核对。5.3 最大似然解调与软判决选择接收端解调采用最大似然准则计算接收点和8个参考星座点的欧氏距离选距离最小的星座点作为判决结果。[~, est_idx] min(abs(rx - const.), [], 2); est_data gray_map_inv(est_idx); % 反查映射表gray_map_inv是gray_map的反向查找表可以由gray_map_inv(gray_map1) 0:7构造。硬判决解调会把全部置信信息都丢掉只输出0/1比特值。对于Hamming和RS这两种块编码硬判决就已经够用了而且实现简单。如果要做软判决译码需要计算每个比特的对数似然比工程复杂度会明显上升。8PSK的软判决通常还要考虑星座点的最小距离和次小距离这超出了基础仿真的范围建议先把硬判决链路跑通再逐步扩展。6. 误码率对比结果与编码增益分析6.1 三种方案的BER曲线解读把Eb/N0从0dB扫到14dB得到的误码率曲线会呈现出比较典型的趋势无编码8PSK在低信噪比段误码率下降缓慢超过某个门限后曲线开始以较快斜率下降。加入Hamming(7,4)后在中高信噪比段曲线斜率略有改善但改善幅度有限在低信噪比段由于码率损失误码率甚至可能高于无编码方案。加入RS(7,3)后曲线斜率变化更明显在高信噪比段能够看到相对明显的增益。绘制曲线用semilogy是基本操作semilogy(EbN0_dB, ber_none, o-, ... EbN0_dB, ber_hamming, s-, ... EbN0_dB, ber_rs, ^-); grid on; xlabel(Eb/N0 (dB)); ylabel(BER); legend(无编码8PSK, Hamming(7,4)8PSK, RS(7,3)8PSK);注意这里的纵坐标是误比特率不是误符号率。8PSK一个符号错1个比特时误比特率是误符号率的三分之一左右统计时要按比特对齐。6.2 “编码增益”到底怎么量化编码增益通常定义为在目标误码率下有编码方案相对无编码方案所需Eb/N0的差值。比如在BER10^-3这个点如果无编码8PSK需要11dB而RS(7,3)8PSK需要10dB那就说RS(7,3)带来了1dB的编码增益。Hamming(7,4)在这个点上可能只能带来0.5dB左右的增益甚至在某些实现中增益为0。坦白讲在纯AWGN信道下Hamming的增益确实有限。它的更大价值在于极低的编解码延迟和实现复杂度。RS的增益更实在一些但代价是更高的复杂度和延迟。仿真时不要只盯着“谁的曲线更靠左”还要考虑码率、延迟和应用场景。6.3 什么情况下此链路会失效有一个关键场景很容易让这套链路暴露短板没有交织器时RS码对突发错误的纠错能力会被浪费。假设某个瞬间噪声脉冲破坏了连续4个8PSK符号放在一个RS(7,3)码字里可能直接超过2个错误符号的容限译码失败。但如果先把符号交织分散到多个码字里每个码字只被破坏1个符号RS就能顺利纠正。同理Hamming(7,4)在强衰落信道下基本不起作用因为它只纠1比特。因此在把这套仿真链路往实际信道推广时一定要考虑加交织器和对应参数。7. 实操踩坑记录给复现者避雷7.1 比特序与符号序混乱问题这个坑我踩过不止一次。编码器输出的比特流是按行排列的0/1向量但8PSK映射需要每3比特一组。如果reshape的方向不对比如默认按列填充而不是按行填充那整个符号序列都会错位解调后误码率高得离谱。建议统一约定所有编码输出都是“先分组组内高位在前”。在代码里固定写成reshape(bits, 3, [])再转置传入后续流程。如果有多个编码器级联每经过一级都检查一次向量长度是否能被3整除。7.2 信噪比定义陷阱用Eb/N0对比不同编码方案时SNR换算必须统一。所有编码器都会降低有效信息速率所以送进AWGN信道的信号功率虽然是相同的但每个信息比特分到的能量不同。换算公式就是早先写过的SNR Eb/N0 10*log10(码率) 10*log10(log2(M))码率是指编码后的信息比特占信道比特的比例。级联时取乘积。如果忘了乘码率带编码的曲线会在横坐标上整体向右偏移看起来似乎“无编码方案更好”这是完全错误的结论。7.3 Gray映射和内置pskmod的不一致我在不同Matlab版本上测试过pskmod(..., gray)的映射结果存在版本差异而且旧版本根本不支持gray选项。为了工程可复现性我强烈建议手动写Gray映射表并且打印出来核对一遍。只要保证“相邻相位只差1比特”这一条这张表怎么排都不影响最终误码率。7.4 可复现性随机数流与中文注释乱码仿真类工程最怕的就是“这次跑出来一个结果下次跑出来另一个结果”。建议在脚本最开头固定随机数种子rng(1);这样整个蒙特卡洛流程完全可复现。在写宝文或论文时也能对实验数据进行复核。另外Matlab的.m文件在中文环境下经常碰到UTF-8和GBK编码不一致导致的注释乱码。解决方法是统一把编辑器编码设置成UTF-8或者在文件开头使用%#codegen和保持纯英文注释减少问题。如果从网页复制代码粘贴进编辑器贴完立即检查注释乱码通常在“保存并重新打开”后才会出现。7.5 性能优化先向量化再并行仿真循环里如果逐比特做Hamming译码速度会非常慢。实测中200帧数据跑到BER10^-4附近串行循环可能需要几分钟而向量化实现可以在几十秒内跑完同量级仿真。Reed-Solomon译码用系统对象批次处理也能明显加速。如果进一步用parfor替换外层Eb/N0扫描循环整条BER曲线几分钟就能出来。我这套工程在把Hamming译码改成全向量化版本后单条曲线生成时间缩短了大约6倍。具体做法是把所有码字排成矩阵一次计算伴随式矩阵再用矩阵索引定位错误列。最后分享一个个人体会真正对8PSK链路有实际增益的往往是RS这类符号级编码而不是Hamming这类简单分组码。但这不意味着Hamming没有价值。很多刚接触信道编码的人把“纠错能力”和“实际增益”划等号实际上Hamming在8PSK这种场景下可能只给你0.5dB的改善却会让实现复杂度成倍增加。反过来看正因为它简单到可以手推每一个矩阵细节用它来理解线性分组码的伴随式原理比直接上手RS要轻松得多。我建议第一次搭这套链路的人先不要急着看RS的黑盒结果而是把Hamming的每一个中间变量都打印出来对照理论自己推一遍然后再用类似思路去分析RS整个知识框架会牢固很多。
返回列表