简介这份资源聚焦数字信号处理与无线通信中的IQ调制器不平衡问题面向射频系统设计、信号处理方向的学习者与工程人员。包内仅含1个MATLAB脚本文件压缩包约7KB体量轻便便于直接运行与二次修改。脚本围绕幅度不平衡与相位不平衡两类典型失真展开可用于模拟IQ调制器的非理想特性、分析其对星座图与信噪比的影响并借助滤波器实现预失真补偿帮助读者理解校正算法的建模思路。已有259人学习下载说明该主题在通信工程实践中具有一定关注度。对于正在研究IQ不平衡建模、预失真滤波器设计或希望用MATLAB快速验证补偿效果的读者这份脚本可作为入门参考与实验起点便于在此基础上扩展参数、对比不同算法性能。1. 从 IQ_imbl6.zip 说起一个压缩包名里藏着的射频工程问题IQ_imbl6.zip这个文件名拆开看IQ是基带信号的同相/正交两路表示imbl6大概率是 imbalance 的缩写加编号zip只是打包格式。真正有价值的信息是这个包里装的不是普通代码而是一组围绕 IQ Modulator 的 IQ imbalance 仿真、补偿或测试数据。做射频、基带算法、通信系统验证的人迟早会碰到这个问题——发射机里 I 路和 Q 路增益不一致、本振相位不是严格 90 度星座图就会从正方形变成歪斜的平行四边形EVM 恶化镜像抑制比掉下去。很多人第一次拿到这类压缩包卡在两步一是 Linux 下解压命令不熟二是解压出来一堆.m、.csv、.mat或.py文件不知道从哪看起。这篇不聊虚的按“先理解 IQ imbalance 是什么、再解压看结构、然后跑最小仿真、最后调参数和排错”的顺序走一遍。适合基带算法工程师、射频测试工程师以及正在做 IQ Modulator 校准的在校研究生。2. IQ imbalance 的数学本质与 IQ Modulator 误差来源2.1 增益失配和相位失配怎么把星座图拧歪理想 IQ Modulator 输出的是s(t) I(t)cos(ωt) - Q(t)sin(ωt)。一旦 I 路增益是(1ε)、Q 路增益是(1-ε)同时本振相位差不是 90 度而是90°φ输出就变成s(t) (1ε)I(t)cos(ωt) - (1-ε)Q(t)sin(ωtφ)展开后除了想要的信号还会在-ω处产生一个镜像分量。镜像抑制比IRR和 ε、φ 的关系近似为IRR(dB) ≈ 10*log10( (ε² φ²/4) / 4 )这里 ε 是幅度相对误差φ 是相位误差弧度。举个例子ε0.011% 增益差、φ0.01 rad约 0.57°IRR 大约只有 -46 dB 左右。想要 IRR 优于 -60 dBε 和 φ 都得压到 0.001 量级。这就是为什么 IQ imbalance 补偿在宽带发射机里是必做项。2.2 从 zip 包结构反推作者意图拿到IQ_imbl6.zip先别急着解压到当前目录。Linux 下用unzip -l看列表比直接unzip安全unzip -l IQ_imbl6.zip输出里重点看三类文件.m或.py是仿真脚本.csv或.txt是 IQ 采样数据.mat是 MATLAB 数据。如果看到README或run_*.m优先读。常见做法是包里会有一个iq_imbalance_model.m和一个iq_compensation.m前者生成带误差的信号后者做补偿。提示如果unzip -l报invalid zip archive: could not find eocd说明文件没下完或传输损坏重新获取即可不要用-FF强行修复。2.3 解压命令与目录规范确认列表没问题后再解压指定目录避免污染当前工作区mkdir -p ~/work/iq_imbl6 unzip -o IQ_imbl6.zip -d ~/work/iq_imbl6 cd ~/work/iq_imbl6 find . -maxdepth 2 -type f | sort-o表示覆盖已存在文件-d指定目标目录。find那行用来快速看清层级。如果包里有中文文件名乱码加-O CP936参数老版本 unzip 支持或者直接用7z x IQ_imbl6.zip代替7z 对编码兼容更好。文件类型常见命名用途仿真脚本*_model.m/*_sim.py生成或补偿 IQ 信号采样数据iq_capture.csv实测或仿真 IQ 对参数文件params.json/config.mε、φ、采样率等说明文档README.md运行顺序和依赖3. 用 Python 复现 IQ imbalance 并做最小补偿验证3.1 生成带增益和相位失配的 IQ 信号不依赖包里的脚本自己写一段最小可运行代码把 ε 和 φ 显式加进去方便后面调参import numpy as np import matplotlib.pyplot as plt # 参数幅度失配 eps相位失配 phi弧度符号数 N eps 0.02 # 2% 增益差 phi 0.03 # 约 1.72 度相位差 N 4096 fs 1e6 # 生成理想 QPSK 基带 rng np.random.default_rng(0) bits rng.integers(0, 2, 2*N) sym (2*bits[0::2]-1) 1j*(2*bits[1::2]-1) sym sym / np.sqrt(2) # 加入 IQ imbalanceI 路乘 (1eps)Q 路乘 (1-eps) 并旋转 phi I np.real(sym) * (1 eps) Q np.imag(sym) * (1 - eps) # 相位失配体现在 Q 路与 I 路的正交性破坏 Q_rot Q * np.cos(phi) I * np.sin(phi) rx I 1j * Q_rot plt.scatter(np.real(rx), np.imag(rx), s2) plt.title(fIQ imbalance eps{eps}, phi{phi}) plt.axis(equal) plt.show()逻辑说明eps控制 I/Q 增益差phi控制正交相位偏差。Q_rot那一步是把相位误差折算到 Q 路等价于本振相位不是严格 90 度。跑完能看到星座点从正方形变成菱形或平行四边形。参数说明eps一般取 0.01~0.05 模拟实际调制器phi取 0.01~0.05 rad 对应 0.57°~2.86°。3.2 用最小二乘估计失配参数补偿的核心是先估计 ε 和 φ。对 QPSK 这类恒模信号可以用统计量# 估计增益失配I 路和 Q 路功率比 gain_ratio np.sqrt(np.mean(I**2) / np.mean(Q**2)) eps_est (gain_ratio - 1) / (gain_ratio 1) # 估计相位失配I*Q 的均值反映正交性 cross np.mean(I * Q) phi_est np.arcsin(2 * cross / np.sqrt(np.mean(I**2) * np.mean(Q**2))) print(feps_est{eps_est:.4f}, phi_est{phi_est:.4f})gain_ratio是两路 RMS 比eps_est由比值反推。cross是 I 和 Q 的互相关理想正交时为 0有相位误差时不为 0。phi_est用arcsin反解。注意这里假设信号均值为零且幅度归一化实测数据要先去掉直流。3.3 补偿矩阵与 IRR 验证估计出参数后构造补偿矩阵# 补偿先校正增益再校正相位 I_comp I / (1 eps_est) Q_comp (Q - I * np.sin(phi_est)) / ((1 - eps_est) * np.cos(phi_est)) rx_comp I_comp 1j * Q_comp # 计算镜像抑制比 def irr_db(sig): f np.fft.fft(sig) f np.fft.fftshift(f) half len(f)//2 img np.sum(np.abs(f[:half])**2) sig_p np.sum(np.abs(f[half:])**2) return 10*np.log10(img/sig_p) print(f补偿前 IRR{irr_db(rx):.2f} dB, 补偿后 IRR{irr_db(rx_comp):.2f} dB)补偿顺序不能反先除增益再减相位耦合项。irr_db用 FFT 把正负频率分开负频能量比正频就是镜像。跑完一般能看到 IRR 改善 20~30 dB。如果改善不明显检查phi_est是否超过 0.1 rad那说明模型和实际不符需要换估计方法。4. 实测数据下的参数调优与常见排错4.1 采样率、直流偏置和量化位数的影响实测 IQ 数据不像仿真那么干净。三个参数最容易翻车采样率、直流偏置、ADC 位数。采样率至少是信号带宽的 2.5 倍否则镜像和信号混叠IRR 算出来是假的。直流偏置会让cross估计偏大补偿前先减均值I I - np.mean(I) Q Q - np.mean(Q)量化位数低比如 8 bit 以下时eps_est的分辨率不够建议先做 4 倍抽取再估计或者用长数据平均。常见做法是采集 10^5 个点以上再估参。4.2 频率相关失配为什么单点补偿不够上面的模型假设 ε 和 φ 与频率无关。但实际 IQ Modulator 的 I/Q 两支路滤波器响应不同失配是频率的函数。这时候要在频域分 bin 估计# 对每个频点估计相位失配 freqs np.fft.fftfreq(len(I), 1/fs) I_f np.fft.fft(I) Q_f np.fft.fft(Q) phi_f np.angle(I_f * np.conj(Q_f)) - np.pi/2phi_f就是每个频点的相位偏差。如果它随频率明显变化超过 0.05 rad单点补偿只能修中心频点带内边缘 IRR 仍然差。这时要用 FIR 滤波器做频域补偿或者查表法。失配类型估计方法补偿手段典型 IRR 改善增益失配RMS 比单系数缩放15~25 dB相位失配I*Q 互相关旋转矩阵20~30 dB频率相关分 bin 相位FIR 滤波器30~40 dB直流偏置均值减均值视偏置大小4.3 解压后脚本跑不通的排查顺序包里的脚本跑不起来按这个顺序查先看依赖MATLAB 脚本需要对应工具箱Python 脚本看requirements.txt再看路径很多脚本用相对路径读../data/解压目录层级变了就找不到最后看版本scipy.signal和numpy.fft的 API 在老版本里有差异。报missing zip entry通常是解压不完整重新解压即可。注意如果脚本里用了eval或动态加载.mat先确认文件没被截断。scipy.io.loadmat报错时用whosmat看变量列表。5. 把 IQ imbalance 补偿嵌进发射机校准流程的实操技巧真实发射机校准不会只跑一次估计。我一般会做三件事第一用两段不同功率的 IQ 数据分别估参看 ε 和 φ 是否随功率漂移漂移大说明调制器工作点没选好第二把补偿系数写进 FPGA 或 DSP 的寄存器前先做定点量化仿真确认量化误差不会把 IRR 拉回去第三校准后扫频验证从带内最低频到最高频取 10 个点每个点算 IRR画成曲线。一个具体技巧估计相位失配时不要直接用全部数据。先用幅度最大的 20% 符号做粗估再用全部数据精估。因为小幅度符号的信噪比低会把cross估计带偏。代码上就是先按np.abs(sym)排序取阈值。thr np.percentile(np.abs(rx), 80) mask np.abs(rx) thr phi_coarse np.arcsin(2*np.mean(np.real(rx[mask])*np.imag(rx[mask])) / np.sqrt(np.mean(np.real(rx[mask])**2)*np.mean(np.imag(rx[mask])**2)))thr取 80 分位mask选出大幅度符号。粗估后再用全部数据做一次精估通常比直接全量估计稳定 3~5 dB。最后把补偿前后的 EVM 和 IRR 都记下来EVM 看整体IRR 看镜像两个指标一起达标才算校准完成。本文还有配套的精品资源点击获取
