ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

NOMA-OFDM MATLAB仿真:从m序列设计到SIC接收机实现

NOMA-OFDM MATLAB仿真:从m序列设计到SIC接收机实现 简介针对NOMA与OFDM联合系统的MATLAB仿真源码包共2个m文件大小2KB适合无线通信方向研究生、工程师以及正在学习5G关键技术的开发者。资源围绕非正交多址接入与正交频分复用提供了noma.m和m_sequence.m两个核心脚本覆盖用户功率分配、多用户检测、伪随机序列生成等关键环节可直接运行学习NOMA功率域复用与OFDM子载波调度原理也可作为课程设计或毕业设计的基础框架。已有894人学习下载说明其在通信仿真实践中具有较高参考价值。借助该压缩包读者可快速搭建NOMA-OFDM仿真实验调整用户数量、功率分配策略和信道条件观察误码率、吞吐量及用户公平性变化深入理解高谱效多址接入的实现细节。整包体积小、结构清晰便于对照代码逐段分析。1. 拆开 noma.m为什么 NOMA-OFDM 仿真要先从序列设计开始很多人第一次打开noma.m的时候会预期看到一个完全摒弃 OFDM 的全新框架但实际第一行代码往往都是在初始化子载波和用户序列。NOMA 的核心反直觉点在于它并不是在物理层把两个信号彻底分开而是故意让它们在时频资源上完全重叠再借助接收端的功率差把用户“拆”开。这个 MATLAB 仿真包正好把noma.m和m_sequence.m两层放在了一起前者处理叠加编码与 SIC 检测后者负责生成用户签名序列。如果你正在做 5G NR 物理层算法评估或者需要对比 NOMA 与 OFDMA 在多用户场景下的吞吐量差异这份代码能直接帮你跑通完整链路并给出 BER、吞吐量和公平性指标。下面我会按“序列生成 → 发射机/接收机实现 → 与 OFDMA 对比 → 贴近 NR 配置”的顺序来拆解整个仿真过程。2. m_sequence.m 背后的移位寄存器逻辑与用户签名生成2.1 从多项式到 m 序列初始化状态与反馈连接m 序列本质上是一个线性反馈移位寄存器LFSR在有限域 GF(2) 上跑出来的伪随机序列周期是 (2^n - 1)。m_sequence.m里的核心参数有两个一个是本原多项式另一个是寄存器的初始状态。这两者决定了序列的周期和相位。在 MATLAB 里如果你有通信工具箱可以直接用comm.PNSequence但为了看清楚寄存器抽头我一般会手写一个移位寄存器版本调试起来更直观% m 序列手写生成器兼容无通信工具箱环境 n_stages 6; % 移位寄存器级数周期为 2^6 - 1 63 reg [1 0 0 0 0 0]; % 初始状态绝对不能全零 m_seq_len 2^n_stages - 1; m_seq zeros(1, m_seq_len); for idx 1:m_seq_len m_seq(idx) reg(n_stages); % 输出最后一级 feedback xor(reg(n_stages), reg(1)); % 本原多项式 x^6 x 1 reg [feedback, reg(1:n_stages - 1)]; % 右移一位并注入反馈 end这段代码的逻辑是基于本原多项式 (f(x) x^6 x 1) 来构造反馈抽头。feedback xor(reg(n_stages), reg(1))表示将寄存器的第 6 级和第 1 级做异或再反馈到输入端。需要特别注意的是初始状态不能是全零否则整个序列会一直输出 0永远跳不出这个死循环。每周期输出的序列长度为 63这个长度在多用户仿真中通常对应一个 OFDM 符号块内的基本扩频单位。2.2 从 m 序列到 Gold 序列互相关与用户区分单个 m 序列只能给一个用户用。在多用户 NOMA 场景下我们需要为不同用户分配不同的签名序列而且这些序列之间的互相关值要尽量低否则在 SIC 解码后残留的互相关干扰会直接抬高用户 2 的误码率。常见的做法是把两个优选对 m 序列异或生成 Gold 序列% 生成第二路 m 序列并移位 5 位 seq1 m_seq; seq2 circshift(m_seq, 5); % 相位偏移产生新的签名 gold_seq xor(seq1, seq2); % Gold 序列 两个 m 序列逐位异或 % 查看互相关特性 [cross_corr, lags] xcorr(gold_seq, seq1); stem(lags, real(cross_corr));这里circshift(m_seq, 5)的作用是改变第 2 个用户的签名相位。Gold 序列的优势在于它的互相关值被限制在三个离散值内比任意两个普通 m 序列的互相关峰值要低得多。在设计 NOMA 系统时我们一般不直接靠序列本身的正交性区分用户功率域区分是主力但序列的互相关性能直接影响 SIC 减法之后的残差噪声水平。换句话说签名序列选得不好功率分配算得再准用户 2 的 BER 也会在高信噪比区间出现平层。2.2.1 自相关峰值在符号同步中的辅助作用除了互相关自相关的峰值特性也值得关注。m 序列的自相关函数是二值的在主瓣有尖锐的峰值旁瓣恒定为 (-1/N)。这个性质可以用来做符号同步即接收端用本地序列与接收信号做滑动相关通过峰值位置确定 OFDM 符号的起始点。在noma.m的整体链路中通常假设理想同步但在实际仿真时少量时偏就会导致子载波间干扰ICI所以理解m_sequence.m的自相关特性能帮你快速判断仿真结果中的 BER 抬升是来自同步偏差还是来自 SIC 错误传播。序列类型周期长度互相关特性MATLAB 生成方式在 NOMA 仿真中的角色m 序列(2^n - 1)三值峰值较高手写移位寄存器或comm.PNSequence基础扰码 / 扩频种子Gold 序列(2^n - 1)有界三值相对更低两个 m 序列异或多用户签名抑制 SIC 残差ZC 序列任意质数理想循环互相关lteZadoffChuSeq参考信号 / 同步序列3. noma.m 的发射机与接收机叠加编码、功率分配和 SIC 检测3.1 功率分配系数 alpha 与叠加编码的 MATLAB 实现NOMA 发射机的核心是叠加编码Superposition Coding。假设有两个用户用户 1 是近端用户信道质量好用户 2 是远端用户信道质量差。为了让两个用户在同一个子载波上都能成功解码需要给用户 2 分配更多功率给用户 1 分配较少功率。这个比例由功率分配系数alpha控制。% 发射机侧两用户 QPSK 符号叠加 N 256; % OFDM 子载波数 snr 20; % 信噪比单位 dB bits1 randi([0 1], N*2, 1); % 用户 1 发送比特 bits2 randi([0 1], N*2, 1); % 用户 2 发送比特 sym1 qammod(bits1, 4, InputType, bit, UnitAveragePower, true); sym2 qammod(bits2, 4, InputType, bit, UnitAveragePower, true); alpha 0.2; % 用户 2 的功率占比通常取 0.1 ~ 0.4 tx_signal sqrt(1 - alpha) .* sym1 sqrt(alpha) .* sym2; % 进入 OFDM 调制IFFT 变换到时域 tx_ofdm ifft(tx_signal, N);这里qammod中的UnitAveragePower设置为true表示将 QPSK 符号的能量归一化到 1这样功率分配系数才能精确反映功率比例。alpha的取值直接影响系统性能alpha越接近 0.5两个用户功率越接近用户 1 解码时需要承受的干扰越大但用户 2 的吞吐量会更高alpha越接近 0用户 1 的 BER 越低但用户 2 的接收信噪比变差。关于功率分配实际仿真中常用的策略有三种功率分配策略核心公式MATLAB 实现要点适用场景固定功率分配(P_1 (1-\alpha)P)直接用sqrt(alpha)缩放符号双用户场景复杂度最低分数阶功率分配FTPA(P_k P \cdot g_k^{-2\alpha} / \sum g_i^{-2\alpha})根据信道增益g_k动态计算缩放因子多用户场景兼顾公平性注水算法(P_k (\mu - \sigma^2 / g_k)^)使用fsolve迭代求解水位线信道差异明显时容量最优FTPA 是 5G 学术论文里最常用的方案它把信道增益 (g_k) 加入功率分配公式让信道差的用户自动获得更高功率从而改善用户公平性。3.2 串行干扰消除SIC的解码顺序与代码逻辑接收端的核心算法是串行干扰消除。SIC 的基本原则是先解码功率大、容易解码的用户然后把这个用户的信号重新编码、调制从接收信号中减去再解码下一个用户。在 NOMA-OFDM 中SIC 是在频域子载波级执行的。% 接收机侧经过 AWGN 信道后先做 FFT 回到频域 rx_ofdm fft(rx_signal, N); % SIC 解码流程先解码用户 1近端用户功率较小 % 注意虽然用户 1 功率小但用户 1 信道好SIC 通常按信道增益降序排列 rx_sym1 rx_ofdm ./ sqrt(1 - alpha); demod_bits1 qamdemod(rx_sym1, 4, OutputType, bit, UnitAveragePower, true); % 重构用户 1 的信号并从接收信号中减去 reconstructed_sym1 qammod(demod_bits1, 4, InputType, bit, UnitAveragePower, true); residual rx_ofdm - sqrt(1 - alpha) .* reconstructed_sym1; % 在残差信号中解码用户 2 rx_sym2 residual ./ sqrt(alpha); demod_bits2 qamdemod(rx_sym2, 4, OutputType, bit, UnitAveragePower, true); % 计算误码率 ber1 biterr(bits1, demod_bits1) / length(bits1); ber2 biterr(bits2, demod_bits2) / length(bits2);这段代码中的关键点在于解码顺序。理论上一旦 SIC 开始执行它默认先解码信道增益较高的用户因为该用户能够承受较大的叠加干扰。如果解码顺序反了用户 2 在存在强干扰的情况下极易出错而且错误会通过重构步骤传播给用户 1。另一个需要留意的是residual的计算很多初学者的代码会忘记对重构信号乘以sqrt(1 - alpha)的功率系数这会导致减法不彻底残留大量干扰。3.3 BER 统计、吞吐量计算与 Jain 公平性指标仿真跑完 SIC 之后自然要统计性能指标。noma.m中通常会计算 BER但如果你需要评估系统整体性能光看 BER 还不够吞吐量和用户公平性同样重要。特别是对比 NOMA 和 OFDMA 时公平性是一个决定性指标。% 吞吐量计算每个 QPSK 符号携带 2 比特 num_symbols N; throughput1 sum(bits1 demod_bits1) / num_symbols; throughput2 sum(bits2 demod_bits2) / num_symbols; % Jain 公平性指数计算 rates [throughput1, throughput2]; fairness sum(rates)^2 / (2 * sum(rates.^2));Jain 公平性指数的取值范围是 0 到 1值越接近 1说明两个用户获得的吞吐量越均衡。当你调整alpha参数时会看到吞吐量和公平性之间的权衡变化。alpha趋近 0.5 时公平性变好但用户 1 的 BER 会上升alpha趋近 0 时用户 2 的吞吐量会显著下降公平性指标恶化。4. NOMA-OFDM 与 OFDMA 的仿真对比从子载波分配到系统容量4.1 OFDMA 的频域多址子载波独占与调度在介绍 NOMA-OFDM 之前先看传统 OFDMA 的仿真方法。OFDMA 把整个频带划分为若干资源块每个用户独占一部分子载波因此用户间完全正交不存在多址干扰。在 MATLAB 中模拟 OFDMA 非常简单就是按索引分配子载波% OFDMA将 N 个子载波分成两组分别分配给两个用户 N 64; user1_subcarriers 1:32; % 用户 1 独占 1~32 号子载波 user2_subcarriers 33:64; % 用户 2 独占 33~64 号子载波 ofdma_freq_domain zeros(1, N); ofdma_freq_domain(user1_subcarriers) sym1; % 用户 1 的符号放在指定子载波 ofdma_freq_domain(user2_subcarriers) sym2; % 用户 2 的符号放在指定子载波 tx_ofdma ifft(ofdma_freq_domain, N); % IFFT 变到时域这段代码里user1_subcarriers和user2_subcarriers是互斥的索引集合。OFDMA 的优点在于接收机处理非常简单接收端只要做一次 FFT按下标取出对应子载波的符号即可不需要额外解码逻辑。但缺点也很明显如果用户 1 的数据量较小它的那部分子载波就会空闲造成频谱资源浪费。4.2 NOMA-OFDM 的同频叠加容量优势与接收机复杂度NOMA-OFDM 改变了 OFDMA 中子载波独占的规则允许两个用户同时使用全部子载波仅用功率差与 SIC 来区分用户。因此它的系统容量更高尤其是在用户间信道质量差异较大的场景。下面这段代码展示了 NOMA-OFDM 发射端的核心差异% NOMA-OFDM所有子载波上同时叠加两个用户信号 noma_freq_domain sqrt(1 - alpha) .* sym1 sqrt(alpha) .* sym2; tx_noma ifft(noma_freq_domain, N);这里的sym1和sym2长度都为 N它们复用的是同一组子载波。NOMA-OFDM 的容量提升来源于叠加编码它让系统过载运行。但其代价是接收机复杂度大幅上升SIC 除了要处理信号重构还要对信道增益进行排序。尤其当用户数增加到 3 到 4 个时SIC 的错误传播会变得非常突出。4.3 典型仿真参数表与“隐式”坑点FFT、CP、归一化在实际仿真时NOMA-OFDM 与 OFDMA 的对比需要放在同一套参数框架下才有意义。我一般会使用下表作为基准配置参数项目OFDMANOMA-OFDM影响说明子载波总数N64 / 256 / 102464 / 256 / 1024FFT 点数必须一致用户数22非正交叠加数循环前缀长度N/4N/4消除多径符号间干扰功率分配系数无需设置alpha 0.2NOMA 特有参数信道编码可选 LDPC可选 LDPC纠错能力接收机算法频域均衡SIC 频域均衡复杂度对比关键仿真中有一个很容易踩的“隐式”坑IFFT 之后的信号功率会随N变化。如果你不对发射信号做功率归一化直接调用awgn(rx_signal, snr, measured)得到的 SNR 会和理论值偏差很大。通常我建议在发射端加一句归一化tx_signal tx_signal / sqrt(mean(abs(tx_signal).^2));确保发射功率为 1。另外循环前缀的添加和去除也容易被忽略在多径信道仿真中如果忘记加 CPOFDM 子载波正交性会被破坏导致 BER 曲线在高 SNR 处出现平层。5. 把仿真往前再推一步5G NR 信道模型与闭环验证技巧5.1 用 nrTDLChannel 替换简单 AWGN 信道基础仿真中我们常常用awgn来模拟信道但真实 5G NR 链路必须考虑时延扩展和多普勒频移。如果你安装了 5G Toolbox我会直接使用nrTDLChannel来替换 AWGN 信道这样得到的结果更接近实际空口下发的性能。% 配置 TDL 信道模型TDL-A 30ns 时延扩展5Hz 多普勒 channel nrTDLChannel(DelayProfile, TDL-A, ... DelaySpread, 30e-9, ... MaximumDopplerShift, 5, ... SampleRate, 1e6); channel.TransmitAntennaSelection [1]; channel.ReceiveAntennaSelection [1];这段代码里的DelayProfile是信道时延分布模型TDL-A对应 5G NR 标准中定义的抽头时延组合。DelaySpread设置为 30ns 代表典型的市区微蜂窝场景。最大多普勒频移 5Hz 对应步行速度。加入信道模型后接收端需要先做信道估计再把 SIC 的解调过程延续下来这样仿真框架才算完整。5.2 通过误码率曲线反向验证 SIC 实现是否正确验证 SIC 实现是否正确有一个很实用的技巧在双用户 AWGN 信道下把两个用户各自的 BER 曲线画出来与理论 QPSK 曲线做对比。理论上用户 2 由于功率高在低 SNR 区域应该先到达零误码点用户 1 在有残留干扰的情况下BER 会比理论曲线略高但最终的斜率应当保持一致。如果你的仿真中两条 BER 曲线在中高 SNR 区间出现平行甚至交叉那基本可以断定 SIC 的重构环节少乘了功率系数或者解码顺序排反了。% 采样 0~25dB 的 SNR 点观察 BER 曲线 snr_range 0:2:24; ber1_curve zeros(size(snr_range)); ber2_curve zeros(size(snr_range)); for snr_idx 1:length(snr_range) % 这里调用你的 NOMA 主函数返回当前 SNR 下两用户 BER [ber1_curve(snr_idx), ber2_curve(snr_idx)] noma_function(snr_range(snr_idx), alpha); end % 绘制半对数坐标曲线便于观察错误平层 semilogy(snr_range, ber1_curve, r-o, snr_range, ber2_curve, b-^);另外在使用noma.m做参数扫描时记得固定随机种子rng(2025)否则每次仿真结果波动较大很难判断参数调整是真实影响还是噪声引起的抖动。按这个流程把序列、叠加编码、SIC 和信道模型串起来你手里的noma.m就不再是一个黑盒而是可以随意修改alpha、用户数、调制阶数并验证 5G 场景的仿真平台。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进