matlab-design-ofdm-system について
非標準の OFDM 送受信機を設計する MATLAB スキルです。サブキャリア割り当て、チャネルシミュレーション、同期や等化を扱い、実装前に必要なパラメーターを確認します。
主な機能
- 01カスタム OFDM 送受信機の設計
- 02サブキャリアとパイロットの設定
- 03AWGN とフェージングチャネルのシミュレーション
- 04同期とチャネル等化の実装
- 05コーディング前のパラメーター確認
活用シーン
- 01MATLAB でのカスタム OFDM リンク構築
- 02ノイズやフェージングの影響のシミュレーション
- 03パイロット追加とチャネル推定
- 04同期と符号化パラメーターの検討
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-design-ofdm-systemインストール後、Claude Code で/matlab-design-ofdm-systemを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
manifest.yamlreferences/ofdm-fading-channel.mdofdm-ldpc-coding.mdofdm-pilots-and-estimation.mdofdm-synchronization.mdofdm-system-guide.md詳細
OFDM システム設計
使用する場面
ユーザーがカスタム(非標準)の OFDM 送信機/受信機の構築、サブキャリア割り当ての設定、OFDM 信号へのノイズの追加、フェージングチャネルを介した OFDM の等化、同期の実装、または LDPC 符号化の追加を希望する場合に、このスキルを使用します。
使用しない場面
標準規格固有の OFDM には、このスキルを使用しないでください(5G NR には 5G Toolbox、Wi-Fi には WLAN Toolbox、4G/LTE には LTE Toolbox、Bluetooth には Bluetooth Toolbox、衛星リンクには Satellite Communications Toolbox を使用してください)。
GATE — コーディングの前に確認する
ユーザーのリクエストで、以下すべてが指定されているか、明確に意図されていない場合は、作業を停止し、コードを生成する前に確認してください。不明な項目を番号付きリストで提示し、ユーザーに、(a)値を指定する、(b)他の制約から値を導出する(例:遅延スプレッドから CP、ドップラーから SCS)、または(c)一般的な既定値を使用する、のどれを希望するか尋ねてください。既定値を推測してはいけません。ユーザーの回答を受け取るまで進めないでください。
- OFDM パラメーター — FFT サイズ、CP 長、サブキャリア間隔、サブキャリア割り当て
- チャネルモデル — AWGN のみ、完全な CSI を用いたフェージング、またはパイロットベースの推定を用いたフェージング
- パイロット — チャネル推定または位相追跡に必要か?
- 符号化 — 符号化なし、または特定のレートで符号化するか?
- 同期 — 完全同期か、タイミング/CFO 推定を含めるか?
必ず守るルール
-
必ず
ofdmmod/ofdmdemodを使用し、ifft/fftを直接呼び出して OFDM を実装してはいけません — これらの関数は、CP の挿入/削除、中心周波数順への並べ替えのためのifftshift/fftshift、パイロット/ヌルサブキャリアの管理を処理します。IFFT/FFT を直接使うと、サブキャリアのマッピングが誤ります(エラーは通知されません)。SISO の入力は[nDataSC × nSym]です。出力は時間領域の列ベクトルです。注: Schmidl-Cox など、DFT 順のサブキャリアマッピングが必要な同期プリアンブルでは、ofdmmodがifftshiftを適用して偶数/奇数ビンの割り当てを変更するため、ifftを直接使用してもかまいません。ウィンドウ処理:ofdmmodはウィンドウ処理をサポートしていません。レイズドコサインウィンドウ処理には、送信機に限りcomm.OFDMModulatorを使用してください(復調には必ずofdmdemod関数を使用してください)。機能の比較についてはreferences/ofdm-system-guide.mdを参照してください。 -
ofdmdemodでは常にsymOffset変数を使用してください —nullidx(第 5 引数)を渡す場合、symOffsetを第 4 引数として明示的に指定する必要があります。symOffsetの既定値はcpLen(CP 全体をスキップ)です。注:タイミング同期が不完全な場合は、cpLen/2のほうが堅牢です。 -
awgnでは明示的な信号電力を使用し、'measured'または0は絶対に使用しないでください —ofdmmodの出力電力は 1W ではありません。MATLAB の 1/N IFFT 正規化により、nActiveSC / nFFT^2になります。awgn(x, snr, 0)を使用すると、ノイズが過剰に加わります。ループの前に一度だけsigPow = 10*log10(nActiveSC / nFFT^2)を計算してください。これは OFDM パラメーターで決まる定数です。 -
周波数領域のチャネル応答には
ofdmChannelResponseを使用してください —H = fft(h, nFFT)を直接計算してはいけません。ofdmmodは内部でifftshiftを使用するため、FFT で直接計算したチャネル応答はサブキャリアマッピングが誤ります。等化には、その結果をofdmEqualizeに渡してください。 -
物理仕様から OFDM パラメーターを導出する場合は、コメント付きで計算過程を示してください — 値を述べるだけでは不十分です。帯域幅、遅延スプレッド、ドップラースプレッドから、サブキャリア間隔、FFT サイズ、CP 長、サンプルレート、ガードサブキャリアなどをどのように計算したかを示してください。各導出手順を説明するコメントを追加してください。
-
バージョンによって利用可否が異なる API を使用する前に、MATLAB のバージョンを確認してください —
ofdmChannelEstimate、ofdmPilotConfig(R2026a)、ldpcPCM(R2025a)などの関数は、古いリリースでは利用できません。ユーザーが以前のバージョンと互換性のあるコードを明示的に求めていない限り、version('-release')を呼び出して現在の MATLAB リリースを取得し、適切な API の使用方法を選んでください。
主な機能
| 機能 | 目的 | 対応開始 |
|---|---|---|
ofdmmod | OFDM 変調(IFFT + CP 挿入) | R2018a |
ofdmdemod | OFDM 復調(CP 除去 + FFT) | R2018a |
ofdmChannelResponse | パスゲインからサブキャリアごとのチャネル応答を取得 | R2023a |
ofdmEqualize | ZF/MMSE 周波数領域等化 | R2022b |
ofdmPilotConfig | パイロットの位置とシンボルの設定 | R2026a |
ofdmChannelEstimate | パイロットベースのチャネル推定(LS + ノイズ除去) | R2026a |
convertSNR | SNR の変換(snrsc、snr、ebno) | R2022a |
awgn | 信号電力を明示して白色ガウスノイズを追加 | — |
サブキャリアの割り当て
サブキャリアのインデックスには中心周波数順を使用します。インデックス 1 は最も負の周波数、インデックス nFFT/2 + 1 は DC、インデックス nFFT は最も正の周波数です。
サブキャリアのインデックスに関するルール:
nullIdxとpilotIdxは、[1, nFFT]の範囲にある 1 始まりの整数のベクトルである必要があります- 互いに重複してはなりません
- DC サブキャリア =
nFFT/2 + 1(必ずヌルにしてください) ofdmmodの入力 X のサイズは[nDataSC x nSym]です。ヌルとパイロットのサブキャリアは除外されますofdmdemodの出力サイズは[nDataSC x nSym]です。ヌルは除去され、パイロットは別途返されます
例(WiFi に似た 64-FFT):
nullIdx = [1:6, 33, 60:64].'; % 12 nulls (6 lower guard + DC + 5 upper guard)
pilotIdx = [12; 26; 40; 54]; % 4 pilots
nActiveSC = nFFT - length(nullIdx); % 52 (data + pilots)
nDataSC = nFFT - length(nullIdx) - length(pilotIdx); % 48
基本的な OFDM Tx/Rx(AWGN)
% Parameters
nFFT = 64; cpLen = 16;
nullIdx = [1:6, 33, 60:64].'; % 12 nulls
nActiveSC = nFFT - length(nullIdx); % 52
nDataSC = nActiveSC; % no pilots
M = 4; % QPSK
nSym = 100;
snr_sc = 10; % dB, per-subcarrier SNR
% Transmit
data = randi([0 M-1], nDataSC, nSym);
modData = pskmod(data, M, InputType="integer");
txSig = ofdmmod(modData, nFFT, cpLen, nullIdx);
% SNR conversion and noise
sigPow = 10*log10(nActiveSC / nFFT^2); % OFDM signal power (dBW)
snr_wb = convertSNR(snr_sc, "snrsc", "snr", ...
FFTLength=nFFT, NumActiveSubcarriers=nActiveSC);
rxSig = awgn(txSig, snr_wb, sigPow);
% Receive
symOffset = cpLen;
rxData = ofdmdemod(rxSig, nFFT, cpLen, symOffset, nullIdx);
demodData = pskdemod(rxData, M, OutputType="integer");
[numErr, ber] = biterr(data(:), demodData(:));
OFDM の SNR の扱い
OFDM シミュレーションにおける標準的なノイズ基準は、サブキャリアあたりの SNR(SNR_sc)です。 Eb/No による理論 BER の比較や、awgn に必要な広帯域 SNR など、別のノイズ指標が必要な場合は、convertSNR を使用して SNR_sc から導出してください。convertSNR の使用パターンと awgn の使い方については、matlab-add-awgn を参照してください。
理論 BER を求める場合: convertSNR(snr_sc, "snr", "ebno", BitsPerSymbol=log2(M)) で SNR_sc を Eb/No に変換し、その後 berawgn(ebno, 'qam', M) を呼び出します。SNR_sc を berawgn に直接渡したり、erfc/qfunc の閉形式の式で Eb/No として使用したりしないでください。SNR_sc ≠ Eb/No です。
AWGN スキルで扱う内容に加え、OFDM 固有の点:
- 信号電力 =
10*log10(nActiveSC / nFFT^2)dBW。これは MATLAB の 1/N IFFT 正規化によるものです nActiveSCにはデータとパイロットのサブキャリアを含めますawgnの 2 つ目の出力からノイズ分散を必ず取得してください:[rxSig, nVar] = awgn(...)。ノイズ分散を SNR の式から手動で計算しないでください。awgnが返す値を使うことで、内部の丸め処理との整合性を保てますofdmdemod後のノイズ分散は nFFT 倍になります:nVar_sc = nVar * nFFT(FFT は N 項を合計します)convertSNRの"snr"タイプは、Eb/No または Es/No から変換する場合、サブキャリアあたりの SNR を表します(OFDM の各サブキャリアは 1 つのシンボルを伝送します)。サブキャリアあたりの SNR を(awgnに渡す)広帯域 SNR に変換するには、convertSNR(snr_sc, "snrsc", "snr", FFTLength=nFFT, NumActiveSubcarriers=nActiveSC)を使用してください。
重要な注意点
awgn(x, snr, 0) は OFDM では誤りです
OFDM 信号の電力は 1 W ではなく、nActiveSC と nFFT に依存します。
% WRONG — assumes unit power (adds ~19 dB too much noise for 64-FFT)
rxSig = awgn(txSig, snr_wb, 0);
% CORRECT — explicit power, capture noise variance
sigPow = 10*log10(nActiveSC / nFFT^2);
[rxSig, nVar] = awgn(txSig, snr_wb, sigPow);
ofdmdemod では symOffset が必須です
symOffset = cpLen; % skip entire CP (or cpLen/2 for imperfect timing)
rxData = ofdmdemod(rxSig, nFFT, cpLen, symOffset, nullIdx);
単一ストリームの場合、変調器/復調器への入力は列ベクトルにする必要があります
すべての Communications Toolbox の変調器(qammod、pskmod など)は列ごとに処理します。各列は独立したチャネル/ストリームです。単一ストリームの OFDM では、ビットまたは整数を必ず列ベクトルとして渡してください。
% WRONG — [nSym x k] matrix: each column is treated as a separate stream
txData = reshape(txBits, nBitsPerSym, []).';
txSymbols = qammod(txData, M, InputType="bit", UnitAveragePower=true);
% CORRECT — column vector in, then reshape output to OFDM grid
txSymbols = qammod(txBits, M, InputType="bit", UnitAveragePower=true);
txSymbols = reshape(txSymbols, nActiveSC, nSym);
複数の列を使用するのは、独立した MIMO ストリームまたは並列のコードワードを同時に変調する場合に限ります。
DC サブキャリアのインデックス
DC = nFFT/2 + 1 です。nFFT=64 の場合、DC のインデックスは 33 です。必ず nullIdx に含めてください。
ofdmEqualize の hEst の次元
デフォルトの DataFormat="3-D" では、hEst の次元は次のとおりです。
[nSC × NS × NR]— 静的:同じ推定値がすべての OFDM シンボルに適用されます[(nSC*nSym) × NS × NR]— 時間変動:シンボルごとの推定値が第 1 次元にまとめられます
[nSC × nSym] をそのまま渡すのは誤りです。次元 2 は nSym ではなく NS として読み取られます。
% WRONG — hEst [nSC x nSym] misinterpreted as [nSC x NS=nSym]
eqData = ofdmEqualize(rxData, hEst_per_sym, nVar);
% CORRECT — collapse first dim to (nSC*nSym), keep stream/antenna dims
eqData = ofdmEqualize(rxData, reshape(hEst_per_sym, [], Ns, Nr), nVar);
パイロットを使用した OFDM
パイロットを挿入するには、pilotIdx とパイロットシンボルを追加の引数として ofdmmod/ofdmdemod に渡します。信号電力は nDataSC だけではなく、nActiveSC(データ+パイロット)に基づきます。
パイロット挿入の完全な例については、references/ofdm-pilots-and-estimation.md を参照してください。
パイロットベースのチャネル推定(R2026a)
完全な CSI を使わずにパイロットベースのチャネル推定を行うには、ofdmPilotConfig + ofdmChannelEstimate を使用します。まだ確認していない場合は、R2026a のワークフローと R2026a より前の手動 LS 方式のどちらを使うかを決める前に、現在の MATLAB バージョンを確認してください。
ofdmChannelEstimate のワークフローは、従来の pilotIdx を使う方法とは異なります。
nullIdxに含めるのはガードバンドのみです(DC は含めません) — DC はアクティブグリッド上の位置となるため、手動でゼロにします。ofdmmod/ofdmdemodにpilotIdx引数はありません — データ、パイロット、DC=0 を含む完全な[nActiveSC x nSym]グリッドを作成し、そのまま渡します。- パイロットの位置は関数の引数ではなく、
ofdmPilotConfigから取得します。 rxSymは 3 次元です:[nActiveSC x nSym x nRx]— SISO の場合も受信アンテナの次元を追加します。
コード例の全容については、references/ofdm-pilots-and-estimation.md を参照してください。
フェージングチャネル上の OFDM
チャネル等化には 2 つの方法があります。
-
完全な CSI(R2023a)—
comm.RayleighChannelのパスゲインとともにofdmChannelResponseを使用します(PathGainsOutputPort=trueが必要です)。info(channel).ChannelFilterCoefficientsからpathFiltersを取得します。時間変動する SISO では、H(:)をofdmEqualizeに渡します。 -
パイロットベースの推定(R2026a)—
ofdmPilotConfig+ofdmChannelEstimateを使用します。
どちらの方法でも、最終的な等化には Algorithm="mmse" を指定して ofdmEqualize を使用します。awgn では必ず信号電力を明示してください('measured' は使用しないでください)。フェージングによって瞬時電力が変化します。
チャネルの設定(Rayleigh/Rician、ドップラー、3GPP プロファイル、ofdmEqualize の次元)については、references/ofdm-fading-channel.md を参照してください。
フェージングチャネルの設定
PathGainsOutputPort=true を指定して comm.RayleighChannel または comm.RicianChannel を設定します。主なルールは次のとおりです。
- 必ず
SampleRateを設定します(既定値は 1 Hz です)。 - 最大パス遅延は CP の継続時間より短くします:
max(PathDelays) < cpLen/SampleRate - 速度からドップラーを計算します:
fd = (velocity * carrierFreq) / physconst('LightSpeed')
設定の全容、3GPP プロファイル、準静的フェージングについては、references/ofdm-fading-channel.md を参照してください。
同期
パイプライン:粗タイミング → CFO 推定 → CFO 補正 → 微細タイミング → OFDM 復調 → 位相追跡
主なルールは次のとおりです。
- CFO の適用/補正には
frequencyOffsetを使用します(手動でのexp(-1j*2*pi*...)は使用しないでください)。 - 相互相関によるタイミング検出には
timingEstimateを使用します。 - シンボル間で補正を適用する前に、パイロットの位相推定値に必ず
unwrapを適用します。
Schmidl-Cox、CP ベースのタイミング検出、Zadoff-Chu プリアンブル、Rx の完全な例については、references/ofdm-synchronization.md を参照してください。
LDPC 符号化
主なルールは次のとおりです。
ldpcEncode/ldpcDecodeは構成オブジェクトとともに使用します(削除済みのcomm.LDPCEncoder/comm.LDPCDecoderは使用しないでください)。- 構成はパリティ検査行列のみから作成します:
H = ldpcPCM(648, 324); encCfg = ldpcEncoderConfig(H); decCfg = ldpcDecoderConfig(H)。スカラー値や名前と値のペアは渡さないでください。ldpcEncoderConfig(648)、ldpcEncoderConfig(648, 1/2)、ldpcDecoderConfig(BlockLength=648)はすべてエラーになります。まだ確認していない場合は、ldpcPCM(R2025a 以降)とldpcQuasiCyclicMatrix(R2021b 以降)のどちらを使うか決めるため、現在の MATLAB バージョンを確認してください。 - 符号化システムの Eb/No を計算する際は、
convertSNRにCodingRateを含めます。 - 適切な LLR スケーリングのために、
qamdemodなどの復調器にNoiseVarianceを渡します。周波数領域に合わせてスケーリングします:nVar_sc = nVar * nFFT - LLR の計算には
OutputType="approxllr"を使用します。
OFDM+LDPC のワークフローと複数コードワードのフレーミングについては、references/ofdm-ldpc-coding.md を参照してください。
高度な機能
以下を参照してください:references/ofdm-system-guide.md:
- 可変 CP 長 — 行ベクトル
cpLensを使用したシンボルごとの CP - 一般的な OFDM 構成 — WiFi に類似したパラメーターセット、LTE に類似したパラメーターセット、5G に類似したパラメーターセット
- SNR の変換 — すべての
convertSNRパターンについては、matlab-add-awgnスキルを参照してください - 軟判定復調のノイズ分散 —
ofdmdemod後のスケーリング
相互参照
matlab-add-awgn— ノイズを追加して SNR 変換を計算する必要がある場合は、このスキルを使用してください。すべてのconvertSNRパターン、awgnの使用方法、ノイズ分散の取得方法を説明しています。
リファレンスの読み込み
パイロットの挿入、パイロットベースのチャネル推定(R2026a の ofdmChannelEstimate)、または R2026a より前の LS 推定について質問された場合は、references/ofdm-pilots-and-estimation.md を読み込んでください。
フェージングチャネルの設定、Rayleigh/Rician の設定、ドップラーの計算、3GPP 遅延プロファイル、または ofdmEqualize の次元処理について質問された場合は、references/ofdm-fading-channel.md を読み込んでください。
タイミング同期、CFO の推定/補正、Schmidl-Cox、プリアンブル設計、またはパイロットベースの位相追跡について質問された場合は、references/ofdm-synchronization.md を読み込んでください。
LDPC 符号化、前方誤り訂正、ldpcEncode/ldpcDecode、軟判定復号のための NoiseVariance、または符号化 BER シミュレーションについて質問された場合は、references/ofdm-ldpc-coding.md を読み込んでください。
SNR 変換の詳細、一般的な OFDM 構成、軟判定復調のノイズ分散、または可変 CP 長について質問された場合は、references/ofdm-system-guide.md を読み込んでください。
Copyright 2026 The MathWorks, Inc.