PAPR 迭代降低算法仿真

1) 算法在做什么

OFDM 时域信号峰值高,本质原因是大量子载波同相叠加。

"迭代降低"一般不是一步到位,而是:

  1. 限幅:把时域样值压到门限 A 以内(非线性,会抬升底噪/产生带外)
  2. 频域滤波:把限幅产生的"带外失真"扔掉(只保留子载波位置的频域分量)
  3. 迭代:重复 1→2,让带内失真慢慢"收敛",PAPR 逐步下降

代价:每次限幅都会引入 带内失真(EVM 类损伤),因此迭代不是越多越好,要在 PAPR 与 EVM/BER 间折衷。


2) 关键参数与建模假设

参数 符号 典型值
子载波总数 N 256
有效子载波 N_used N(或 N-保护 tone)
调制 M 16-QAM / QPSK
过采样率(时域) L 4
限幅门限(幅度) A 由目标 PAPR₀ 换算
迭代次数 N_iter 3~8
帧数(Monte Carlo) N_frame ≥500(CCDF 才稳)

限幅门限与 PAPR 的关系

如果你希望"限幅门限对应某个目标 PAPR₀(dB)":

A=σx10PAPR010A = \sigma_x \sqrt{10^{\frac{PAPR_0}{10}}}A=σx1010PAPR0

其中 (σx2=E∣x(n)∣2\sigma_x^2=E\|x(n)\|\^2σx2=E∣x(n)∣2)(用一段训练样本估计,或直接归一化平均功率为 1)。


3) 核心函数:迭代限幅 + 频域滤波(ICF)

这里我用 频域把"非子载波位置置零" 来模拟"只保留有用子载波"------等价于理想的子载波内滤波。

matlab 复制代码
function x_out = icf_ofdm(y, A, N_iter, Nfft, N_used, cp_len)
% ICF_OFDM  Iterative Clipping and Frequency-Domain Filtering
% y      : 时域 OFDM 符号 (Nfft+L*Nfft? 这里约定 y 长度为 Nfft)
% A      : 限幅门限 (幅度)
% N_iter : 迭代次数
% Nfft   : FFT 点数
% N_used : 有效子载波数(这里用简单中心映射示意)
% cp_len : CP 长度(不影响限幅核,但你要统一接口就留着)

x = y(:);

% --- 子载波索引:简单取中心 N_used ---
kc = floor((Nfft - N_used)/2) + 1;
idx_used = kc : (kc+N_used-1);

for it = 1:N_iter
    % 1) 限幅
    mag = abs(x);
    phase = exp(1j*angle(x));
    mask = (mag > A);
    x_c = x;
    x_c(mask) = A .* phase(mask);          % 硬限幅(你可换软限幅)
    d = x_c - x;                            % 限幅失真

    % 2) 回频域,只保留子载波位置(滤掉带外)
    D = fft(d, Nfft);
    D_filter = zeros(Nfft,1);
    D_filter(idx_used) = D(idx_used);      % 子载波内留着

    % 3) 重建时域
    x = x_c - ifft(D, Nfft);                % 经典写法:x_new = x_c - ifft(带外)
    % 等价理解:只保留带内 => x = ifft(D_filter)

    % 可选:再做一个小保护(避免数值反弹)
    x(abs(x)>A) = A .* exp(1j*angle(x(abs(x)>A)));
end

x_out = x;
end

如果你要更"射频味",把频域滤波换成 FIR/矩形窗(对应 sinc 时域)保留 DC/左右对称子载波 即可;结构不变。


4) 完整仿真骨架:产生 OFDM → 迭代降低 → PAPR/CCDF

4.1 主脚本

matlab 复制代码
clear; clc; close all;

%% === 参数 ===
Nfft   = 256;
N_used = Nfft;          % 这里先不用虚拟子载波,方便看清 PAPR
M      = 16;            % QAM
L      = 4;             % 过采样倍数
N_sym  = 1;             % 每帧 OFDM 符号数(PAPR 通常不依赖多符号)
cp_len = Nfft/8;

% 迭代参数
N_iter = 5;
PAPR0_dB = 7;          % 你想"对应的限幅门限"参考(不是保证值)

N_frame = 1000;        % Monte-Carlo

%% === 归一化:令 E[|x|^2]=1 ===
% 16-QAM 平均能量 (格雷/单位平均功率归一化可自己定)
const = qammod(0:M-1, M, ...
    InputType="integer", UnitAveragePower=true);
% const =  (2*(randi([0 1],N,1)-0.5) + 1j*(2*(randi([0 1],N,1)-0.5))) / sqrt(2); % QPSK 例子

PAPR_vec_raw = nan(N_frame,1);
PAPR_vec_icf = nan(N_frame,1);

rng(42);

for f = 1:N_frame
    %% 1) 随机数据
    b  = randi([0 M-1], N_used*N_sym, 1);
    Xf = qammod(b, M, InputType="integer", UnitAveragePower=true);

    %% 2) 映射到 FFT 位置(中心映射)
    kc = floor((Nfft - N_used)/2)+1;
    X  = zeros(Nfft,1);
    X(kc:kc+N_used-1) = Xf;

    %% 3) IFFT → 过采样可在此做(最简:IFFT 后插值;更"标准"用 L*Nfft)
    x_raw = ifft(X, Nfft)*sqrt(Nfft);  % 归一化看你习惯;下面我们用功率归一化

    % --- 功率归一化使得 E[|x|^2]=1 ---
    x_raw = x_raw / sqrt(mean(abs(x_raw).^2));

    % 为省事:这里先不做 L>1 插值(PAPR 仍可比,但更严格的要插值)
    x = x_raw;

    %% 4) 原始 PAPR
    power_inst = abs(x).^2;
    PAPR_raw(f) = 10*log10( max(power_inst) / mean(power_inst) );

    %% 5) 限幅门限
    A = sqrt(mean(power_inst)) * sqrt(10^(PAPR0_dB/10));

    %% 6) ICF
    x_icf = icf_ofdm(x, A, N_iter, Nfft, N_used, cp_len);

    % 重新功率归一化(可选,便于公平比较)
    x_icf = x_icf / sqrt(mean(abs(x_icf).^2));
    power_inst2 = abs(x_icf).^2;
    PAPR_icf(f) = 10*log10( max(power_inst2) / mean(power_inst2) );
end

%% === CCDF ===
PAPR_db = 0:0.1:12;
ccdf_raw = arrayfun(@(t) mean(PAPR_raw > t), PAPR_db);
ccdf_icf = arrayfun(@(t) mean(PAPR_icf > t), PAPR_db);

figure; semilogy(PAPR_db, ccdf_raw, 'k--','LineWidth',2); hold on; grid on;
semilogy(PAPR_db, ccdf_icf,'r-','LineWidth',2);
xlabel('PAPR_0 (dB)'); ylabel('CCDF = Prob(PAPR>PAPR_0)');
legend('Raw OFDM','ICF (iter='+string(N_iter)+')');
title('OFDM PAPR 降低:迭代限幅+频域滤波');

参考代码 PAPR 迭代降低算法仿真 www.youwenfan.com/contentcsv/81410.html

5) 3 个"仿真坑"

  1. PAPR 看起来偏低 / 没峰

    → 你很可能没做过采样 。真 PAPR 需要用至少 (L\ge4) 的过采样(IFFT 插值或更长 IFFT)否则会漏掉峰。

    做法:用 Nfft_up = L*Nfft,把频域填到更大网格再做 IFFT。

  2. 迭代后波形"反而更怪"

    → 常见原因:你限幅门限太低(A 太小)→ 强削波 → 带内 EVM 暴增;或者你滤波没正确"只保留子载波/带内"。先把 N_iter=1 跑通、看时域波形再往上加。

  3. CCDF 不稳(曲线毛毛躁躁)

    N_frame 不够。PAPR 尾部是稀有事件,通常要 几千帧 才平滑(看你精度需求)。