NOMA-OFDM MATLAB仿真:从m序列设计到SIC接收机实现
2026/9/10 11:49:25 网站建设 项目流程

简介:针对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.mm_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_subcarriersuser2_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);

这里的sym1sym2长度都为 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。另外,循环前缀的添加和去除也容易被忽略,在多径信道仿真中,如果忘记加 CP,OFDM 子载波正交性会被破坏,导致 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 场景的仿真平台。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询