简介:这份资源面向无线通信方向的研究生、科研人员与工程师,提供OFDM与OTFS两种宽带调制技术在多径衰落信道下的完整仿真实现,帮助理解二者在高速移动与频率选择性衰落场景中的性能差异。压缩包共9个文件,全部为m脚本文件,整体约11KB,涵盖主流程入口、OFDM调制解调、ISFFT/SFFT变换、多径信道建模、均衡处理、数据生成与结果绘图等模块,结构紧凑、便于逐函数阅读与二次修改。已有468人学习下载,说明其在相关课程设计与科研入门中具有一定参考价值。读者可据此搭建瑞利或莱斯衰落下的链路级仿真,计算误码率与符号误率,对比OFDM与OTFS的优劣,并借助可视化图表直观观察不同参数下的系统表现,为后续通信系统设计提供可复用的代码基础与实验思路。
1. 从一条多径信道说起:OFDM 和 OTFS 到底该怎么放在同一个仿真里
做宽带无线通信仿真的同学,大概率都遇到过这个场景:链路预算算得好好的,一放进多径信道,OFDM 的误码率曲线就开始“玄学抖动”——有时比理论值高两三个 dB,有时换个时延扩展又突然变好。等你把 OTFS 也加进来对比,发现它在高多普勒下确实稳,但低速场景又没占到便宜。问题往往不在调制本身,而在于你有没有把两套波形放在同一套信道、同一套采样率、同一套接收机框架下跑。
这个标题讲的就是这件事:用一套可复现的仿真,把 OFDM 和 OTFS 同时丢进宽带多径衰落信道里,看它们在时延扩展和多普勒扩展下的真实表现。它解决的是“选型靠感觉”的问题,适合做链路级仿真、波形对比、毕设或预研的工程师。下面我按自己搭这套仿真的顺序,把参数、代码和踩过的坑一次讲清楚。
2. 先把信道模型立住:多径衰落不是加个高斯噪声就完事
2.1 为什么宽带场景必须用抽头延迟线而不是单径瑞利
窄带仿真里,一个复高斯乘性因子就能代表衰落。但宽带无线通信系统的带宽一旦到几十 MHz,符号周期缩短到微秒级,多径时延扩展就和符号周期可比了。这时候信道不再是“一个系数”,而是一串抽头:每条径有自己的时延、复增益和多普勒频移。常见做法是抽头延迟线模型,抽头间隔取采样周期,抽头数由最大时延扩展除以采样周期决定。
我一般用 Jakes 模型生成每条径的时变增益,或者更省事地用 sum-of-sinusoids 近似。关键参数有三个:最大时延扩展、多普勒频移、抽头功率分布。功率分布常用指数衰减,因为实测宽带信道大多近似指数型功率延迟谱。如果你直接给每条径等功率,仿真出来的误码率会偏乐观,这是很多人第一条曲线就对不上的原因。
2.2 用 MATLAB 搭一条可复现的多径信道
下面这段代码生成一条抽头延迟线信道,参数可调,输出每个时刻的信道冲激响应。它同时适用于 OFDM 和 OTFS,因为两者最终都要经过同一个卷积信道。
% 多径抽头延迟线信道生成 % 参数说明: % Fs 采样率(Hz) % tau_max 最大时延扩展(s) % fd_max 最大多普勒频移(Hz) % Ns 仿真样点数 % pdp_exp 功率延迟谱指数衰减因子 function h = multipath_channel(Fs, tau_max, fd_max, Ns, pdp_exp) Ts = 1/Fs; L = ceil(tau_max/Ts) + 1; % 抽头数 tau = (0:L-1)*Ts; % 各抽头时延 pdp = exp(-pdp_exp * tau / tau_max); pdp = pdp / sum(pdp); % 归一化总功率为1 h = zeros(L, Ns); t = (0:Ns-1)*Ts; for l = 1:L % 每条径用单频多普勒近似,实际可用Jakes求和 fd = fd_max * cos(2*pi*rand); % 随机到达角 phase = 2*pi*rand; h(l,:) = sqrt(pdp(l)) * exp(1j*(2*pi*fd*t + phase)); end end逻辑上,先由最大时延扩展定抽头数,再由指数衰减定各抽头平均功率,最后给每条径一个多普勒频移和随机初相。参数怎么改:tau_max决定频率选择性强度,fd_max决定时间选择性强度,pdp_exp越大功率越集中在首径。失败时先看L是不是远大于循环前缀长度,如果是,说明时延扩展超出了 CP 保护范围,OFDM 会出现 ISI,曲线会突然恶化。
注意:多普勒频移的符号和到达角有关,仿真里随机取即可,但同一抽头在不同时刻的相位要连续,否则会引入额外频谱扩展。
2.3 信道与波形的采样率必须对齐
OFDM 和 OTFS 的符号周期、子载波间隔不同,但仿真里必须统一到一个采样率上,否则信道抽头时延对不上。常见做法是取两者子载波间隔的最小公倍数对应的采样率,或者直接用一个足够高的过采样率,再在接收端做匹配滤波。我一般让Fs = N_fft * delta_f,其中delta_f是 OFDM 子载波间隔,OTFS 也复用这个采样率,只是它的时频网格不同。这样信道模型只建一次,两套波形共用,对比才公平。
3. OFDM 链路怎么搭:从子载波间隔到 CP 长度的实操
3.1 子载波间隔和 FFT 点数的选择逻辑
OFDM 子载波间隔直接决定符号周期。宽带系统里常见 15 kHz、30 kHz、60 kHz 几档。间隔越小,符号越长,对时延扩展的容忍度越高,但多普勒容忍度越低。做仿真时我一般先定带宽和 FFT 点数,再反推子载波间隔。比如 20 MHz 带宽、1024 点 FFT,子载波间隔就是 19.53 kHz,接近 15 kHz 档。如果你要对比 OTFS,OTFS 的时频网格可以复用同样的子载波间隔,只是它把符号铺在延迟-多普勒域。
CP 长度要覆盖最大时延扩展。经验值是 CP 长度取最大时延扩展的 1.2 到 1.5 倍。太短会引入 ISI,太长会浪费频谱效率。仿真里可以扫一遍 CP 长度,看误码率曲线什么时候不再改善,那个点就是合理值。
3.2 一个最小可跑的 OFDM 收发链路
下面代码实现 OFDM 调制、过信道、加噪声、接收解调,输出误码率。它和上一节的信道函数直接衔接。
% OFDM 链路仿真 % 参数: % N_fft FFT点数 % N_cp 循环前缀长度 % N_sym OFDM符号数 % mod_order 调制阶数(如4表示QPSK) % snr_db 信噪比(dB) function ber = ofdm_link(N_fft, N_cp, N_sym, mod_order, snr_db, h) N_data = N_fft - N_fft/4; % 留1/4子载波做保护 bits = randi([0 mod_order-1], N_data*N_sym*log2(mod_order), 1); sym = qammod(bits, mod_order, 'UnitAveragePower', true); sym = reshape(sym, N_data, N_sym); % 子载波映射,中间留空 grid = zeros(N_fft, N_sym); grid(N_fft/8+1:end-N_fft/8, :) = sym; % IFFT并加CP tx = ifft(grid, N_fft); tx_cp = [tx(end-N_cp+1:end, :); tx]; tx_serial = tx_cp(:); % 过信道:对每根接收天线做卷积 L = size(h,1); rx_serial = zeros(length(tx_serial)+L-1, 1); for l = 1:L rx_serial(l:l+length(tx_serial)-1) = ... rx_serial(l:l+length(tx_serial)-1) + h(l,1:length(tx_serial)).' .* tx_serial; end % 加高斯噪声 rx_serial = awgn(rx_serial, snr_db, 'measured'); % 去CP并FFT rx_serial = rx_serial(1:length(tx_serial)); rx_cp = reshape(rx_serial, N_fft+N_cp, N_sym); rx = rx_cp(N_cp+1:end, :); rx_grid = fft(rx, N_fft); % 单抽头均衡(假设已知信道频响) H = fft(h(:,1), N_fft); rx_eq = rx_grid ./ H; rx_sym = rx_eq(N_fft/8+1:end-N_fft/8, :); rx_bits = qamdemod(rx_sym(:), mod_order, 'UnitAveragePower', true); ber = sum(rx_bits ~= bits) / length(bits); end逻辑说明:先产生比特并映射成 QAM 符号,铺到子载波上,IFFT 后加 CP,串行过信道。接收端去 CP、FFT,再用已知信道频响做单抽头均衡。参数怎么改:N_cp要大于信道最大时延对应的样点数;mod_order改 4、16、64 看不同谱效;snr_db扫 0 到 30 看曲线。失败时先看均衡后的星座图,如果发散,多半是 CP 不够或信道估计不准。
提示:仿真里假设了理想信道估计。实际系统要加导频和插值,那会额外引入估计误差,曲线会再差 1 到 2 dB。
3.3 把 OTFS 也接进同一套信道
OTFS 的核心是把符号放在延迟-多普勒域,再做二维变换到时频域,最后用 OFDM 调制发射。所以它和 OFDM 共用前端,只是预编码不同。常见做法是:先做 ISFFT 得到时频域信号,再走 OFDM 的 IFFT 和 CP。接收端反过来。这样你只需要在 OFDM 链路前面加一个 OTFS 预编码模块,信道和噪声完全复用。
4. OTFS 接入:延迟-多普勒域预编码和接收端均衡
4.1 ISFFT 和 SFFT 的实现细节
OTFS 的调制过程是:把 M×N 的延迟-多普勒域符号矩阵先做沿延迟维的 FFT,再做沿多普勒维的 IFFT,得到时频域网格。接收端做逆变换。M 对应延迟维抽头数,N 对应多普勒维符号数。M 和 N 的乘积等于一帧的总资源单元数。仿真里我一般取 M 等于信道抽头数的 2 到 4 倍,N 取 14 或 28,和 OFDM 的符号数对齐。
% OTFS 预编码:延迟-多普勒域到时间域 % 输入 x_dd: M x N 复符号 % 输出 tx_serial: 串行时域信号 function tx_serial = otfs_modulate(x_dd, N_fft, N_cp) [M, N] = size(x_dd); % ISFFT: 沿延迟维FFT,沿多普勒维IFFT X_tf = fft(x_dd, M, 1) / sqrt(M); X_tf = ifft(X_tf, N, 2) * sqrt(N); % 映射到OFDM网格:每个时频格点做一个OFDM符号 % 这里简化:把X_tf按列做IFFT tx = ifft(X_tf, N_fft, 1); tx_cp = [tx(end-N_cp+1:end, :); tx]; tx_serial = tx_cp(:); end逻辑上,ISFFT 把延迟-多普勒域的稀疏信道响应变成时频域的准静态响应,这样接收端均衡更简单。参数怎么改:M 越大,延迟分辨率越高,但一帧时长变长,多普勒分辨率下降;N 越大,多普勒分辨率越高,但延迟分辨率下降。失败时看接收端星座图,如果旋转,多半是多普勒补偿没做对。
4.2 接收端均衡:从时频域到延迟-多普勒域
接收端先做 OFDM 解调,得到时频域网格,再做 SFFT 回到延迟-多普勒域。在延迟-多普勒域里,信道表现为每个符号乘一个复增益,均衡就是逐点除法。但实际信道有分数多普勒和分数时延,会引入能量泄漏,需要加窗或做迭代均衡。仿真里如果只做整数抽头,可以先用逐点除法看基线性能。
% OTFS 接收端:时频域到延迟-多普勒域 function x_dd_est = otfs_demodulate(rx_grid, M, N, H_dd) % SFFT: 沿延迟维IFFT,沿多普勒维FFT X_tf = rx_grid; x_dd = ifft(X_tf, M, 1) * sqrt(M); x_dd = fft(x_dd, N, 2) / sqrt(N); % 逐点均衡 x_dd_est = x_dd ./ H_dd; end参数说明:H_dd是延迟-多普勒域信道响应,可以由信道抽头直接映射得到。如果信道时变快,H_dd每帧都要更新。失败时先看H_dd有没有零值,有零值说明该格点深衰落,需要加正则化。
4.3 OFDM 和 OTFS 在同一信道下的对比方法
要公平对比,必须保证两者占用相同带宽、相同总功率、相同信道实现。我一般固定随机种子,让信道抽头序列一致,然后分别跑 OFDM 和 OTFS,扫信噪比,画误码率曲线。对比时看两个维度:时延扩展大时谁先出现误码平台,多普勒大时谁先崩。通常 OTFS 在高多普勒下优势明显,OFDM 在低多普勒下实现简单、开销小。
5. 避坑与排查:仿真跑不通时先看这五条
5.1 误码率曲线在高信噪比下不降反升
现象:信噪比超过 20 dB 后,误码率不再下降,甚至翘起来。原因:多是信道估计误差或均衡矩阵接近奇异,也可能是 CP 长度不足导致 ISI。解决:先检查 CP 是否覆盖最大时延,再把均衡改成 MMSE,加一个小的正则因子。
5.2 OTFS 接收端星座图整体旋转
现象:解调后星座图旋转一个固定角度。原因:多普勒频移没有补偿,或者 ISFFT/SFFT 的归一化因子用错。解决:在延迟-多普勒域估计公共相位,做一次相位旋转校正;检查 FFT/IFFT 的缩放系数是否成对。
5.3 OFDM 频谱旁瓣泄漏严重
现象:发射频谱带外泄漏大,邻道干扰明显。原因:子载波映射时没有留保护带,或者用了矩形窗。解决:在频域边缘留 1/8 到 1/4 的保护子载波,必要时加升余弦窗。
5.4 仿真速度慢到跑不完一次扫频
现象:一帧几万个样点,扫 20 个信噪比要跑几小时。原因:用了三重循环逐样点卷积。解决:把信道卷积改成filter或频域相乘,MATLAB 里用conv的'same'模式,或者把抽头延迟线写成矩阵乘法。
5.5 两套波形对比时结果不可比
现象:OFDM 和 OTFS 的误码率曲线交叉点飘忽。原因:两者总发射功率、带宽占用或信道实现不一致。解决:固定随机种子,统一总功率归一化,确保两者经过同一个h矩阵,并且接收端噪声功率按相同信噪比定义。
6. 进阶技巧:用分数间隔抽头逼近真实宽带信道
前面用的抽头延迟线是整数倍采样周期,真实信道时延往往是连续的。整数抽头会低估时延扩展,让曲线偏乐观。我一般会加一层分数间隔处理:把每条径的时延拆成整数部分和分数部分,分数部分用 sinc 插值或者一阶多项式近似。这样信道更接近实测,OTFS 的延迟-多普勒域稀疏性也更真实。
具体做法是:对每条径,先算tau_l / Ts,取整数部分做抽头位置,小数部分用相邻两个抽头做线性插值。代码上就是在生成h之后,再做一个分数延迟滤波器。参数上,分数间隔取 1/4 或 1/8 采样周期就够,再细收益很小。
验证方法:固定信噪比,扫最大时延扩展,看误码率曲线是否平滑。如果出现台阶,说明分数延迟没处理好。另一个验证是看信道频响的相干带宽,和理论值1/(2*pi*tau_max)对比,偏差在 10% 以内就算合理。
我自己的习惯是:每换一组信道参数,先跑一遍无噪声回环,确认收发符号能对上,再加噪声扫曲线。这个“后悔药”能省掉大量排查时间。希望帮到你。
本文还有配套的精品资源,点击获取