
简介这份资源面向通信工程、无线网络方向的学习者与研究者聚焦LTE系统级仿真中的下行链路场景帮助理解从eNodeB到UE的完整交互流程。内容围绕物理层处理、信道模型、资源分配、多用户调度与干扰处理等关键环节展开并涉及链路级与系统级仿真的差异以及SISO单输入单输出模型下的简化分析思路。压缩包共40个文件以m脚本文件为主涵盖参数配置、信道建模、编解码、调制解调、资源映射与结果可视化等模块整体约35KB结构紧凑便于按流程阅读。目前已有330人学习下载适合作为LTE下行链路系统级仿真的入门参考与算法验证素材。读者可借此梳理仿真主流程理解调度、CQI反馈与信道估计等机制如何协同并在此基础上评估不同设计决策对网络容量、覆盖与服务质量的影响。1. SISO.zip 里的 LTE 仿真从链路到系统级一套代码怎么跑通下行你拿到一个叫SISO.zip的压缩包里面塞着 LTE 仿真代码标签写着链路仿真、系统级仿真、下行链路。第一反应大概率是这俩不是一回事吗链路级看的是单个用户、单条无线链路里比特怎么变成波形、误码率多少系统级看的是多个小区、多个用户怎么调度、干扰怎么算、吞吐量多少。把两者塞进一个包里说明作者想做的是一条从物理层到网络层的完整验证链而不是只跑个 BER 曲线就完事。SISO 在这里不是“简单”的意思它是单输入单输出一根发射天线对一根接收天线。LTE 下行链路本身支持 MIMO但 SISO 是理解整个链路的最短路径——没有层映射、没有预编码OFDM 符号生成、参考信号、信道估计、均衡、解调、解速率匹配、Turbo 译码这些环节一个不少。系统级仿真则是在链路级给出的链路性能曲线基础上做多小区干扰建模和调度。这个包的价值在于它把两个层级串起来了你能看到一条完整的数据流从调度器分配资源块开始到接收端 CRC 校验结束。适合谁看如果你正在做 LTE 物理层算法验证、想理解系统级仿真里链路到系统的映射关系、或者需要一套可修改的 SISO 下行链路参考代码这个方向值得投入时间。但前提是你得知道每一层在干什么否则跑出来的图你也不知道对不对。下面按“先立住理论、再动手复现、最后避坑”的顺序拆开讲。2. 链路级仿真SISO 下行链路从比特到波形的完整链路2.1 为什么 SISO 下行链路是理解 LTE 物理层的最短路径LTE 下行采用 OFDMA每个子帧 1ms包含 14 个 OFDM 符号常规 CP资源块 RB 在频域占 12 个子载波、时域占 0.5ms。SISO 配置下发射端只有一根天线接收端也只有一根所以不需要考虑层映射和预编码矩阵。整个链路可以拆成发射机和接收机两大部分。发射机侧CRC 添加、码块分割、Turbo 编码、速率匹配、加扰、调制映射、层映射SISO 下直接透传、预编码SISO 下单位矩阵、RE 映射、OFDM 符号生成。接收机侧反过来OFDM 解调、信道估计、均衡、解调、解扰、解速率匹配、Turbo 译码、CRC 校验。为什么说 SISO 是最短路径因为 MIMO 的很多环节在 SISO 下退化成恒等操作你可以先把注意力放在信道编码和 OFDM 调制解调上。等 SISO 跑通了再往上加 MIMO 只是多几个矩阵运算。常见做法是先用 SISO 验证链路预算和误码率曲线再扩展到 2x2、4x4。链路级仿真的核心输出是 BLER块错误率对 SNR 的曲线。这条曲线是系统级仿真的输入——系统级里每个用户根据瞬时 SINR 查表得到 BLER再决定这次传输是否成功。所以链路级仿真的精度直接决定系统级仿真的可信度。2.2 用 MATLAB 跑通 SISO 下行链路的最小代码框架下面是一个可复现的最小链路级仿真框架覆盖从传输块到 CRC 校验的完整流程。代码按 LTE 标准 36.212 和 36.211 的关键步骤组织参数可调。% SISO LTE 下行链路级仿真最小框架 % 参数设置 N_RB 6; % 资源块数对应 1.4MHz 带宽 N_sc N_RB * 12; % 子载波数 N_sym 14; % 每子帧 OFDM 符号数 cp_len 4; % 常规 CP 长度第一个符号 mod_order 4; % QPSK 调制 snr_db 0:2:20; % SNR 扫描范围 n_iter 1000; % 每 SNR 点仿真次数 % 传输块大小简化固定 TBS tbs 152; % 对应 6RB、MCS 0 的 TBS bler zeros(size(snr_db)); for s 1:length(snr_db) err_cnt 0; for it 1:n_iter % 发射端生成随机比特 tx_bits randi([0 1], tbs, 1); % CRC 添加24A crc_poly [1 1 0 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 1 1 1 1 0 1 1]; tx_crc [tx_bits; mod(sum(tx_bits .* crc_poly(1:end-1)), 2)]; % Turbo 编码1/3 码率 % 实际使用 lteTurboEncode此处用占位函数 encoded lteTurboEncode(tx_crc); % 速率匹配简化截断到可用 RE 数 n_re N_sc * N_sym - N_sc; % 减去参考信号占用 rate_matched encoded(1:min(length(encoded), n_re * 2)); % 加扰 c_init 0; % 简化小区 ID 为 0 scrambled mod(rate_matched lteScrambling(c_init, length(rate_matched)), 2); % 调制映射 QPSK symbols lteQPSKModulate(scrambled); % RE 映射简化直接填满网格 grid zeros(N_sc, N_sym); grid(1:length(symbols)) symbols; % OFDM 调制 tx_waveform ifft(grid, N_sc); tx_waveform [tx_waveform(end-cp_len1:end); tx_waveform]; % 信道AWGN rx_waveform awgn(tx_waveform, snr_db(s), measured); % 接收端OFDM 解调 rx_waveform rx_waveform(cp_len1:end); rx_grid fft(rx_waveform, N_sc); % 信道估计理想估计 h_est ones(N_sc, 1); % 均衡ZF eq_symbols rx_grid(1:length(symbols)) ./ h_est(1:length(symbols)); % 解调 rx_bits lteQPSKDemodulate(eq_symbols); % 解扰 descrambled mod(rx_bits lteScrambling(c_init, length(rx_bits)), 2); % 解速率匹配简化取前 tbs24 位 decoded_input descrambled(1:tbs24); % Turbo 译码 rx_crc lteTurboDecode(decoded_input); % CRC 校验 if ~isequal(rx_crc(1:tbs), tx_bits) err_cnt err_cnt 1; end end bler(s) err_cnt / n_iter; end % 绘制 BLER 曲线 semilogy(snr_db, bler, b-o); xlabel(SNR (dB)); ylabel(BLER); grid on; title(SISO LTE 下行链路 BLER 曲线);这段代码的逻辑说明发射端从随机比特开始依次做 CRC 添加、Turbo 编码、速率匹配、加扰、QPSK 调制、RE 映射、OFDM 调制。信道用 AWGN 模拟。接收端做相反操作最后比较译码后的比特和原始比特。参数说明N_RB控制带宽mod_order控制调制方式snr_db是扫描范围n_iter决定统计精度。tbs需要和N_RB、mod_order匹配否则速率匹配会出问题。实际跑的时候lteTurboEncode和lteTurboDecode需要替换成 MATLAB LTE Toolbox 的函数或者自己实现的 Turbo 编解码。如果没有 Toolbox可以用comm.TurboEncoder和comm.TurboDecoder替代。加扰序列的生成需要按 36.211 的伪随机序列公式实现这里用占位函数表示。跑通之后你会得到一条 BLER 曲线。QPSK 在 6RB 配置下BLER 降到 0.1 大概需要 6-8 dB SNR。如果曲线明显偏移先检查速率匹配的比特数对不对再检查 Turbo 译码的迭代次数。2.3 链路级仿真的三个必调参数TBS、MCS 和信道模型TBS传输块大小决定了一次传输携带多少信息比特。LTE 里 TBS 由 MCS 和分配的 RB 数共同决定查 36.213 的表 7.1.7.2.1-1。TBS 选小了吞吐量上不去选大了BLER 会飙升。常见做法是固定 RB 数扫描 MCS找到 BLER 不超过 0.1 的最大 MCS。MCS调制编码方案控制调制阶数和码率。QPSK 对应低 MCS16QAM 和 64QAM 对应高 MCS。SISO 下行链路里QPSK 的鲁棒性最好64QAM 在 SNR 低于 15dB 时基本不可用。调 MCS 的时候注意码率不能超过 1否则速率匹配会重复比特译码性能反而下降。信道模型决定仿真结果的可信度。AWGN 是最简单的但实际 LTE 下行要面对 EPA、EVA、ETU 等多径信道。EPA 时延扩展小适合步行场景ETU 时延扩展大适合高速场景。如果只跑 AWGNBLER 曲线会偏乐观系统级仿真里调度器会做出错误决策。我一般先用 AWGN 验证链路正确性再换 EPA 看性能损失最后用 ETU 确认边界。提示Turbo 译码的迭代次数对 BLER 影响很大。迭代 4 次和迭代 8 次在低 SNR 下 BLER 可能差一个数量级。仿真时固定迭代次数不要用自适应停止准则否则不同 SNR 点的比较不公平。3. 系统级仿真多小区干扰下 SISO 下行链路的调度与吞吐3.1 系统级仿真到底在算什么从链路 BLER 到小区吞吐量链路级仿真输出的是单条链路的 BLER 曲线系统级仿真要回答的是一个小区里 20 个用户同时要数据调度器怎么分配 RB每个用户能拿到多少吞吐量小区边缘用户会不会饿死。SISO 下行系统级仿真的核心模块包括小区拓扑生成、用户撒点、路径损耗和阴影衰落、调度器、链路自适应、HARQ、干扰计算。小区拓扑常见的是 7 小区 21 扇区或者 19 小区 57 扇区。每个小区中心放一个 eNodeB用户均匀撒在小区内。路径损耗用 36.942 的公式阴影衰落用对数正态分布相关系数 0.5。用户到服务小区的路损算一次到干扰小区的路损算一次两者相减得到 SINR。调度器是系统级仿真的灵魂。常见的有轮询、比例公平、最大 C/I。轮询保证公平但吞吐量低最大 C/I 吞吐量高但边缘用户没资源比例公平是折中。SISO 下行里比例公平的优先级度量是瞬时速率除以平均速率瞬时速率由 SINR 和可用 MCS 决定。链路自适应根据 SINR 选 MCS。SINR 高选高阶调制SINR 低选 QPSK。选完 MCS 后查链路级 BLER 曲线如果 BLER 超过 0.1 就降 MCS。HARQ 负责重传第一次传错了第二次合并再译码。系统级仿真里 HARQ 通常简化成第一次传输成功率由 BLER 决定失败后重传一次两次都失败就丢包。吞吐量统计分两种小区平均吞吐量和小区边缘吞吐量5% 用户。平均吞吐量看整体效率边缘吞吐量看覆盖质量。SISO 下行在 1.4MHz 带宽下平均吞吐量大概 1-2 Mbps边缘吞吐量 200-500 kbps。如果边缘吞吐量太低说明调度器太偏向中心用户需要调整比例公平的公平性因子。3.2 用 MATLAB 搭一个 7 小区 SISO 下行系统级仿真骨架下面是一个可运行的系统级仿真骨架覆盖小区拓扑、用户撒点、路损计算、比例公平调度和吞吐量统计。代码结构按“初始化 → 每 TTI 调度 → 统计”组织。% SISO LTE 下行系统级仿真骨架 % 小区拓扑7 小区每小区 3 扇区 % 用户撒点每扇区 10 个用户 % 调度器比例公平 % 仿真时长1000 TTI clear; clc; % 参数设置 n_cell 7; n_sector 3; n_ue_per_sector 10; n_tti 1000; n_rb 6; % 1.4MHz 带宽 tx_power_dbm 43; % 每扇区发射功率 noise_dbm -174 10*log10(180e3) 7; % 噪声功率 pathloss_exp 3.76; % 路损指数 shadow_sigma 8; % 阴影衰落标准差 dB % 生成小区和用户位置 cell_radius 500; % 小区半径 500m ue_pos zeros(n_cell, n_sector, n_ue_per_sector, 2); for c 1:n_cell for s 1:n_sector for u 1:n_ue_per_sector % 极坐标撒点距离小区中心 50-500m r 50 (cell_radius - 50) * rand(); theta 2*pi*rand(); ue_pos(c,s,u,:) [r*cos(theta), r*sin(theta)]; end end end % 计算路损和 SINR sinr zeros(n_cell, n_sector, n_ue_per_sector); for c 1:n_cell for s 1:n_sector for u 1:n_ue_per_sector % 服务小区距离 d_serv sqrt(sum(ue_pos(c,s,u,:).^2)); pl_serv 128.1 37.6*log10(d_serv/1000); shadow_serv shadow_sigma * randn(); % 干扰小区简化只算同频邻区 interference 0; for cc 1:n_cell if cc c, continue; end d_int sqrt(sum((ue_pos(c,s,u,:) - [cc*1000, 0]).^2)); pl_int 128.1 37.6*log10(d_int/1000); shadow_int shadow_sigma * randn(); interference interference 10^((tx_power_dbm - pl_int - shadow_int)/10); end % SINR 计算 signal_power 10^((tx_power_dbm - pl_serv - shadow_serv)/10); noise_power 10^(noise_dbm/10); sinr(c,s,u) 10*log10(signal_power / (interference noise_power)); end end end % 比例公平调度 avg_rate ones(n_cell, n_sector, n_ue_per_sector) * 1e6; % 初始平均速率 total_rate zeros(n_cell, n_sector, n_ue_per_sector); for tti 1:n_tti for c 1:n_cell for s 1:n_sector % 计算每个用户的瞬时速率查表简化 inst_rate zeros(1, n_ue_per_sector); for u 1:n_ue_per_sector % SINR 映射到 MCS再映射到速率 if sinr(c,s,u) 15 mcs 9; % 64QAM 高码率 elseif sinr(c,s,u) 10 mcs 6; % 16QAM elseif sinr(c,s,u) 5 mcs 3; % QPSK 高码率 else mcs 0; % QPSK 低码率 end inst_rate(u) n_rb * 12 * 14 * 2 * (mcs1) / 14 / 1e-3; % 简化速率计算 end % 比例公平优先级 priority inst_rate ./ avg_rate(c,s,:); [~, best_ue] max(priority); % 分配 RB 给优先级最高的用户 total_rate(c,s,best_ue) total_rate(c,s,best_ue) inst_rate(best_ue); % 更新平均速率滑动窗口 alpha 0.01; avg_rate(c,s,best_ue) (1-alpha)*avg_rate(c,s,best_ue) alpha*inst_rate(best_ue); end end end % 统计吞吐量 cell_avg_throughput squeeze(mean(mean(total_rate, 3), 2)) / n_tti; cell_edge_throughput zeros(n_cell, 1); for c 1:n_cell ue_throughput squeeze(mean(total_rate(c,:,:), 2)) / n_tti; cell_edge_throughput(c) prctile(ue_throughput, 5); end fprintf(小区平均吞吐量: %.2f Mbps\n, mean(cell_avg_throughput)/1e6); fprintf(小区边缘吞吐量: %.2f Mbps\n, mean(cell_edge_throughput)/1e6);这段代码的逻辑说明先撒用户算每个用户到服务小区和干扰小区的路损得到 SINR。然后每个 TTI 做比例公平调度根据 SINR 选 MCS算瞬时速率按优先级分配 RB。最后统计平均吞吐量和边缘吞吐量。参数说明n_cell和n_sector控制拓扑规模n_ue_per_sector控制负载tx_power_dbm和noise_dbm决定 SNR 基线pathloss_exp和shadow_sigma决定信道条件。实际跑的时候速率计算需要替换成 36.213 的 TBS 表MCS 选择需要根据 BLER 目标做链路自适应。干扰计算只算了同频邻区实际还要考虑扇区间干扰和不同频率复用因子。比例公平的滑动窗口因子alpha控制公平性越小越公平但收敛越慢。跑通之后你会看到小区平均吞吐量和边缘吞吐量。如果边缘吞吐量太低调大alpha或者换轮询调度器对比。如果平均吞吐量太低检查 MCS 选择是不是太保守。3.3 系统级仿真里链路到系统的映射BLER 曲线怎么用链路级仿真输出的 BLER 曲线在系统级里有两个用途一是链路自适应选 MCS二是 HARQ 重传决策。具体做法是系统级里每个用户根据 SINR 查表得到 BLER如果 BLER 小于 0.1这次传输成功如果大于 0.1降一阶 MCS 再查直到 BLER 满足要求。HARQ 第一次传输失败后第二次传输的 SINR 会合并第一次的等效 SINR 提高 3dB 左右再查 BLER 决定是否成功。这个映射关系是系统级仿真的黑匣子。链路级 BLER 曲线不准系统级结果就不可信。常见问题是链路级只跑了 AWGN系统级却用多径信道导致 BLER 被低估调度器选了过高的 MCS实际吞吐量反而下降。解决办法是链路级和系统级用同一套信道模型或者链路级多跑几种信道系统级按场景查不同的表。另一个坑是链路级的 SNR 和系统级的 SINR 定义不一致。链路级 SNR 是信号功率比噪声功率系统级 SINR 是信号功率比干扰加噪声功率。映射的时候要把干扰功率折算进去否则会高估链路性能。我一般会在链路级仿真里加一个干扰等效噪声的步骤把 SINR 转成等效 SNR 再查表。注意系统级仿真里 HARQ 的重传合并增益不要拍脑袋定。IR增量冗余和 CC chase combining的增益不一样IR 大概 3-5dBCC 大概 2-3dB。用错了会导致边缘吞吐量偏差 20% 以上。4. 避坑与排查SISO LTE 仿真里最容易翻车的五个地方4.1 现象BLER 曲线在低 SNR 下不降反升原因Turbo 译码的迭代次数设成了自适应停止低 SNR 下迭代次数不够译码器输出随机比特CRC 校验失败率反而比不译码还高。或者速率匹配的比特数超过了编码器输出重复比特导致译码器输入置信度混乱。解决固定 Turbo 译码迭代次数为 6-8 次不要用早停。检查速率匹配的输出长度确保不超过编码器输出长度。如果用了打孔确认打孔模式符合 36.212 的规则。4.2 现象系统级仿真里所有用户的 SINR 都是负的原因路损公式的单位搞错了。36.942 的路损公式里距离单位是千米如果用户位置用米算路损会多算 60dB。或者发射功率用了 dBm路损用了 dB相减的时候没统一。解决统一单位。距离转成千米再代入路损公式发射功率和路损都用 dB 域计算。检查噪声功率的计算-174 10*log10(带宽)得到的是 dBm和发射功率 dBm 一致。4.3 现象比例公平调度器只服务一个用户原因平均速率的初始值设得太小第一个用户被调度后平均速率更新优先级骤降但其他用户的平均速率还是初始值优先级计算出来还是第一个用户最高。或者滑动窗口因子alpha太大平均速率更新太快优先级波动剧烈。解决平均速率初始值设成瞬时速率的量级比如 1e6。alpha设成 0.01 到 0.001 之间让平均速率平滑变化。如果还是只服务一个用户检查优先级计算是不是用了瞬时速率除以平均速率而不是反过来。4.4 现象OFDM 解调后星座图旋转原因CP 长度不对。常规 CP 第一个符号是 4 个采样点其余符号是 3 个采样点针对 1.4MHz 带宽。如果所有符号都用 4 个采样点第二个符号开始相位偏移累积星座图旋转。解决按 36.211 的表 6.12-1 设置 CP 长度。1.4MHz 带宽下第一个符号 CP4其余 CP3。如果带宽变了CP 长度也要跟着变。检查 OFDM 解调时去掉的 CP 长度和发射端加的一致。4.5 现象系统级吞吐量远高于链路级理论值原因链路自适应选 MCS 的时候没有查 BLER 曲线直接按 SINR 线性映射到最高 MCS。或者 HARQ 重传次数设成了无限次实际不可能。解决链路自适应必须查 BLER 表确保选中的 MCS 对应的 BLER 不超过 0.1。HARQ 最大重传次数设成 3-4 次超过就丢包。检查速率计算是不是用了理论峰值实际要乘上码率和 BLER 成功率。5. 进阶技巧用链路级结果反推系统级参数以及一个验证习惯链路级和系统级分开跑最大的问题是两边参数对不上。我一般会做一个交叉验证在链路级里固定 SNR跑出 BLER在系统级里固定 SINR查同一个 BLER 表看两边在相同误块率下的 SNR 和 SINR 差多少。如果差超过 2dB说明有一边的信道模型或者噪声计算有问题。具体做法是链路级跑 AWGN记录 BLER0.1 时的 SNR。系统级里把干扰关掉只留噪声跑同一个用户记录 BLER0.1 时的 SINR。理论上这两个值应该相等。如果不等先检查系统级的噪声功率是不是和链路级一致再检查路损和发射功率的折算。另一个习惯是每次改完调度器或者链路自适应先跑 100 个 TTI 看趋势不要直接跑 1000 个。100 个 TTI 足够看出吞吐量是不是在合理范围不对就停下来查参数。等趋势对了再跑长仿真出统计结果。这个习惯帮我省了很多次通宵跑完发现结果全错的后悔药。还有一个技巧是用链路级的 Turbo 译码迭代次数来反推系统级的 HARQ 增益。链路级里迭代 4 次和迭代 8 次的 BLER 差多少系统级里 HARQ 重传合并的增益就大概是多少。这样不用单独做 HARQ 仿真直接从链路级结果里估。最后说一个验证方法把系统级仿真里的 SINR 分布画出来和 3GPP 的典型值对比。SISO 下行 1.4MHz小区中心 SINR 大概 15-20dB边缘大概 -5 到 0dB。如果分布明显偏移先查路损和阴影衰落再查干扰计算。这个对比花不了几分钟但能快速判断仿真是不是在正轨上。希望帮到你。本文还有配套的精品资源点击获取