matlab-analyze-ams-waveform について
Mixed-Signal Blockset のユーティリティで混合信号波形を解析する MATLAB スキルです。回路やシミュレーションのエンジニア向けに、タイミング、位相雑音、ジッター、PLL のロック時間、リサンプリング、ADC/DAC 特性評価、HSpice データの読み込みと測定・レポート手順を扱います。
主な機能
- 01位相雑音測定とジッター換算
- 02クロックジッターと PLL ロック時間の解析
- 03波形タイミングとアンチエイリアスリサンプリング
- 04ADC/DAC の INL/DNL 測定と校正
- 05HSpice シミュレーションデータの読み込み
活用シーン
- 01VCO または PLL シミュレーションの位相雑音測定
- 02周期ジッターとサイクル間ジッターの算出
- 03ADC または DAC の直線性評価
- 04HSpice の過渡、AC、スイープデータの読み込み
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-analyze-ams-waveformインストール後、Claude Code で/matlab-analyze-ams-waveformを入力して読み込まれたか確認します。
同梱ファイルmanifest.yaml
詳細
AMS 波形の解析 — ミックスドシグナル ブロックセットのユーティリティ
Mixed-Signal Blockset の msblksutilities 関数を使用して波形データを解析します。
タイミング、位相雑音、ジッター、ロック時間、リサンプリング、INL/DNL、ADC/DAC のキャリブレーション、HSpice データのインポートを扱います。
使用する場合
- 時間領域の VCO/PLL シミュレーション出力から位相雑音を測定する
- クロック信号から周期ジッターまたはサイクル間ジッターを計算する
- 非一様(可変ステップソルバー)データを一様なグリッドにリサンプリングする
- デジタル波形から立ち上がり/立ち下がり時間、デューティサイクルを測定する
- ADC/DAC の特性評価のために INL/DNL を計算する
- HSpice シミュレーション結果(.tr0、.ac0、.sw0)をインポートする
- 位相雑音プロファイルを積分 RMS ジッターに変換する
使用しない場合
- Signal Processing Toolbox によるスペクトル解析(FFT、PSD、スペクトログラム)— SPT を直接使用してください
- 信号品質の指標(SNR、SINAD、THD、SFDR)— SPT 関数(
snr、thd、sfdr、sinad)を直接使用してください - フィルタリングまたは包絡線検出 — Signal Processing Toolbox を直接使用してください
- アンチエイリアス付きリサンプリングが不要な、一様サンプリング済みデータ
ワークフロー指示:位相雑音パラメーターの確認
ユーザーが波形データから位相雑音を測定するよう依頼した場合、先に周波数オフセット点を確認してください。
- 質問:「どの周波数オフセットで位相雑音を測定しますか?
デフォルト:
[10e3, 100e3, 1e6, 10e6]Hz — Enter キーを押してこれらの値を使用するか、 独自の値を指定してください。」 - オフセットが確定したら、最小オフセットを基準に RBW を提案してください。
RBW = min(offsets) / 2(例:最小オフセットが 10 kHz の場合は 5 kHz)。次のように伝えます。 「RBW = X Hz(最小オフセット / 2)を使用します。別の値を希望する場合はお知らせください。」 - ユーザーが変更を希望しない限り、測定を続行します。
これにより、ユーザーが事前に API シグネチャを把握していなくても、用途に合った測定を行えます。
フェーズ 1:波形データの取り込み
1.1 データソースの特定
% From workspace variables
x = t; y = v;
% From .mat file
data = load('waveform.mat');
x = data.time; y = data.voltage;
% From .csv
data = readmatrix('waveform.csv');
x = data(:,1); y = data(:,2);
% From HSpice transient (.tr0)
tr0Reader('sim.tr0', 'output.mat');
data = load('output.mat');
% From HSpice AC (.ac0)
ac0Reader('sim.ac0', 'output.mat');
% From HSpice DC sweep (.sw0)
sw0Reader('sim.sw0', 'output.mat');
% From Simulink simulation output (timeseries in logsout)
sig = simOut.logsout.get('signalName').Values;
x = sig.Time(:); % column vector
y = squeeze(sig.Data(:)); % column vector — squeeze removes trailing dims
1.2 基本的な波形の概要
解析の前に、必ず概要を出力します。
fprintf('=== Waveform Summary ===\n');
fprintf('Points : %d\n', numel(x));
fprintf('X range : [%.6g, %.6g]\n', min(x), max(x));
fprintf('Y range : [%.6g, %.6g]\n', min(y), max(y));
fprintf('Y mean : %.6g\n', mean(y));
fprintf('Y RMS : %.6g\n', rms(y));
if all(diff(x) > 0)
dx = diff(x);
if max(dx)/min(dx) < 1.01, uStr = 'yes'; else, uStr = 'no'; end
fprintf('X step : %.6g (uniform: %s)\n', median(dx), uStr);
if median(dx) > 0
fprintf('Sample rate: %.6g Hz\n', 1/median(dx));
end
end
1.3 MSB 解析メニュー
Available MSB analyses for time-domain waveform:
--- Timing Measurements ---
[1] Rise time — timeDomainSignal2RiseTime
[2] Fall time — timeDomainSignal2FallTime
[3] Duty cycle — timeDomainSignal2DutyCycle
--- Clock / PLL Measurements ---
[4] Phase noise from frequency-domain data — phaseNoiseMeasure (default Type='Frequency')
[5] Phase noise from time-domain voltage — phaseNoiseMeasure (Type='Time')
[6] Period jitter & cycle-to-cycle jitter — clockJitterMeasure
[7] Phase noise to jitter conversion — phaseNoiseToJitter
[8] Lock time from control voltage — lockTimeMeasure
--- Resampling ---
[9] Anti-aliased resampling — lowpassResample
--- ADC/DAC Characterization ---
[10] INL / DNL measurement — inldnl
[11] ADC calibration — calibrateADC
[12] DAC calibration — calibrateDAC
--- Data Import ---
[13] HSpice transient (.tr0) — tr0Reader
[14] HSpice AC (.ac0) — ac0Reader
[15] HSpice DC sweep (.sw0) — sw0Reader
--- Frequency-Domain Utilities ---
[16] Interpolate/extrapolate to new grid — interpExtrap
[17] Laplace to biquad SOS — laplace2sos
フェーズ 2:解析の実行
2.1 タイミング測定
% Rise time — 3rd arg is [low high] percent reference levels (required)
rt = timeDomainSignal2RiseTime(x, y, [10 90]);
fprintf('Rise time (10%%-90%%): mean = %.4g s (std = %.4g s, N=%d)\n', ...
mean(rt), std(rt), numel(rt));
% Fall time — same 3-arg signature
ft = timeDomainSignal2FallTime(x, y, [10 90]);
fprintf('Fall time (90%%-10%%): mean = %.4g s (std = %.4g s, N=%d)\n', ...
mean(ft), std(ft), numel(ft));
% Duty cycle — returns per-cycle values for multi-cycle waveforms
dc = timeDomainSignal2DutyCycle(x, y);
fprintf('Duty cycle: mean = %.4f%%, std = %.4f%%\n', mean(dc)*100, std(dc)*100);
2.2 位相雑音の測定
事前確認(必須): 測定前にシミュレーション時間を確認します。
% Sim duration pre-check — STOP if insufficient
minDuration = 10 / min(FrOffset); % need >= 10 cycles of lowest offset
simDuration = x(end) - x(1);
if simDuration < minDuration
error('Simulation too short: %.4g s < %.4g s needed for %.0f Hz offset.\nIncrease sim stop time to >= %.4g s.', ...
simDuration, minDuration, min(FrOffset), minDuration);
end
% From time-domain voltage waveform (MSB variable-step simulation output)
% Type='Time' is REQUIRED — extracts phase via zero-crossings internally
Rbw = 1e3; % resolution bandwidth (Hz)
FrOffset = [10e3 100e3 1e6 10e6]; % offsets to measure
[PnAtOffsets, freqAxis, pnProfile] = phaseNoiseMeasure( ...
x(:), y(:), Rbw, FrOffset, 'on', 'PN Measurement', ...
-inf, ... % 7th arg: target PN level for plot overlay (-inf = no target line)
Type='Time');
% Note: To reduce ripple in pnProfile, use smaller RBW (increases freq resolution)
% or increase simulation duration. SpectralAverages is a PLL Testbench block
% parameter, NOT a phaseNoiseMeasure argument.
% From frequency-domain data (e.g., imported spectrum analyzer measurement)
% Default Type='Frequency': Xin=freq offset vector, Yin=power in dBc/Hz
[PnAtOffsets, freqAxis, pnProfile] = phaseNoiseMeasure( ...
freqOffsets, pnPower_dBcHz, Rbw, FrOffset, 'on', 'PN from Spectrum');
fprintf('Phase Noise Results:\n');
for k = 1:numel(FrOffset)
fprintf(' @ %.0f kHz : %.1f dBc/Hz\n', FrOffset(k)/1e3, PnAtOffsets(k));
end
% Save figure for Claude to read
figPath = fullfile(tempdir, 'phase_noise_plot.png');
saveas(gcf, figPath);
fprintf('Phase noise figure saved to: %s\n', figPath);
2.3 ジッター測定
必須の追加作業: 位相雑音を測定した後(セクション 2.2)は必ず、phaseNoiseToJitter を使用して積分 RMS ジッターを計算します。
ジッターはピコ秒単位で報告してください。これはエンジニアが仕様と比較する指標です。
% Clock jitter from time-domain waveform
% Returns 2 outputs: [periodJitter, c2cJitter] (RMS values)
% threshold MUST cross the signal — use midpoint or known logic level
% Inputs must be column vectors
threshold = (max(y) + min(y)) / 2;
clockFreq = 1e9; % expected clock frequency (Hz)
[periodJitter, c2cJitter] = clockJitterMeasure(x(:), y(:), threshold, clockFreq);
fprintf('Period jitter (RMS): %.4f ps\n', periodJitter * 1e12);
fprintf('C2C jitter (RMS) : %.4f ps\n', c2cJitter * 1e12);
% Convert phase noise profile to jitter
% Exclude DC bin (freqAxis==0) — integration from 0 Hz returns Inf
validIdx = freqAxis > 0;
[jitterRad, jitterDeg, jitterSec] = phaseNoiseToJitter( ...
freqAxis(validIdx), pnProfile(validIdx), Frequency=carrierFreq);
fprintf('RMS jitter from PN : %.4f ps\n', jitterSec * 1e12);
2.4 ロック時間の測定
% x = time, y = control voltage (loop filter output)
% lockTimeMeasure takes (voltage, time, tolerance) — note: voltage FIRST
% Both must be column vectors
x_col = x(:); y_col = y(:);
targetVoltage = y_col(end); % assume final value is lock voltage
errorTol = 0.01; % 1% tolerance
lockTime = lockTimeMeasure(y_col, x_col, errorTol);
fprintf('Lock time (%.0f%% tolerance): %.4g s\n', errorTol*100, lockTime);
推奨方法: PLL Testbench ブロックがある場合は、測定済みのロック時間(get_param(tbBlk, 'UserData').lockTime)を使用します。周波数誤差の検出は、電圧の整定より正確です。
2.5 リサンプリング
% Anti-aliased resampling to new sample time
Ts_new = 1e-9;
tq = (x(1) : Ts_new : x(end))';
cfg.OutputRiseFall = Ts_new;
cfg.NDelay = 1;
cfg.SampleMode = 'variable';
cfg.CausalMode = 'off';
y_resampled = lowpassResample(x, y, tq, cfg);
x_resampled = tq;
2.6 INL/DNL の測定
% ADC: uses transition-based fit (works on ANY input stimulus, not just ramps)
result = inldnl(Analog, Digital, Range, 'ADC', ...
'INLMethod', 'All', 'DNLMethod', 'All', ...
'OffsetErrorUnit', 'All', 'GainErrorUnit', 'All');
fprintf('Max |Endpoint INL|: %.4f LSB\n', max(abs(result.EndpointINL)));
fprintf('Max |Endpoint DNL|: %.4f LSB\n', max(abs(result.EndpointDNL)));
fprintf('Offset Error: %.4f LSB\n', result.OffsetErrorLSB);
fprintf('Gain Error: %.4f LSB\n', result.GainErrorLSB);
% DAC: uses center-based fit (FitMode='centers' is default for DAC)
result_dac = inldnl(Analog, Digital, Range, 'DAC', ...
'INLMethod', 'All', 'DNLMethod', 'All');
重要: ヒストグラムベースの DNL(コードビン数)は使用しないでください。この方法には、特定の入力刺激(PDF が既知のランプまたは正弦波)が必要です。inldnl 関数は遷移ベースの解析を使用するため、任意の入力に対応できます。
ADC と DAC: ADC には FitMode='transitions'(デフォルト)を使用し、DAC には FitMode='centers' を使用します。誤ったフィットモードを使用すると、結果が不正確になります。
2.7 ADC/DAC のキャリブレーション
% Calibrate ADC: correct offset and gain errors
y_cal = calibrateADC(Digital, NBits, Polarity);
% Or infer errors from measured data:
y_cal = calibrateADC(Analog, Digital, Range, 'OffsetError', oe, 'GainError', ge);
% Calibrate DAC:
y_cal = calibrateDAC(Digital, NBits, Polarity);
% Or with reference/bias:
y_cal = calibrateDAC(Digital, Analog, Ref, Bias);
フェーズ 3:位相雑音プロットの解釈
3.1 傾きの解析
| 領域 | 傾き | 物理的な意味 |
|---|---|---|
| キャリア近傍(< ループ帯域幅) | -30 dB/dec | 1/f^3 — フリッカー FM 雑音が支配的 |
| 中間領域 | -20 dB/dec | 1/f^2 — 白色 FM/VCO の熱雑音 |
| 遠方領域(> ループ帯域幅) | -20 dB/dec、その後フラット | VCO の開ループ雑音、その後に熱雑音フロア |
3.2 ループ帯域幅のピーク
ピークまたは山(3~10 dB)は、PLL の閉ループ帯域幅を示します。 10 dB を超える場合、ループが低減衰(位相余裕が小さい)になっている可能性があります。
3.3 雑音フロア
遠方領域のフロア(1~10 MHz を超えるオフセット)は、VCO の熱雑音とシミュレーションの数値雑音によって決まります。VCO の開ループ仕様と一致するはずです。
3.4 アーティファクトとリップル
- 高周波リップル:スペクトル平均が不十分です
- 不要なトーン:frac-N PLL では、fPFD の倍数で発生することが予想されます
- 低オフセットでフラットまたは上昇:シミュレーション時間が短すぎます(W9 を参照)
3.5 解析例
Phase noise from a 1 GHz VCO (MSB sim, 100 us, zero-crossing):
@ 10 kHz : -51.8 dBc/Hz <- marginal (sim too short)
@ 100 kHz : -82.4 dBc/Hz <- in 1/f^2 region, reasonable
@ 1 MHz : -98.4 dBc/Hz <- approaching noise floor
@ 10 MHz : -127.6 dBc/Hz <- VCO open-loop thermal floor
Observations:
- -20 dB/dec slope from 10-80 kHz confirms white FM noise
- Hump at 100-300 kHz suggests loop BW artifact
- Floor at -128 dBc/Hz consistent with VCO open-loop spec
- 10 kHz result unreliable -- need >= 1 ms sim for clean data
フェーズ 4:レポート作成
4.1 確認用の図を保存する
figPath = fullfile(tempdir, 'analysis_plot.png');
saveas(gcf, figPath);
fprintf('Figure saved to: %s\n', figPath);
MATLAB が figPath を出力したら、Read ツールで PNG を開き、
観察結果(フェーズ 3 の傾き、アーティファクト、ノイズフロア)を提示します。
4.2 HTML レポートを生成する
次の項目を含む HTML レポートを必ず生成します。
- ヘッダー(データファイル、日付、手法、MATLAB のバージョン)
- 暗色テーマの
<pre>ブロック内の MATLAB コンソール出力 - 波形の概要テーブル
- 測定設定テーブル
- 数値結果テーブル
file:///URL を使った図の埋め込み- フェーズ 3 の観察結果
- 推奨事項
- フッター:"Generated by Claude Code -- Waveform Analysis Skill -- {date}"
命名規則:データと同じディレクトリに report_{datafile_stem}.html を作成します。
クイックリファレンス:MSB 関数のソース
| 関数 | 用途 |
|---|---|
phaseNoiseMeasure | 位相ノイズ測定 |
phaseNoiseToJitter | 位相ノイズからジッターへの変換 |
clockJitterMeasure | 周期ジッターとサイクル間ジッター |
lockTimeMeasure | PLL のロック時間 |
timeDomainSignal2RiseTime | 立ち上がり時間 |
timeDomainSignal2FallTime | 立ち下がり時間 |
timeDomainSignal2DutyCycle | デューティサイクル |
inldnl | INL/DNL 測定 |
calibrateADC | ADC 誤差のキャリブレーション |
calibrateDAC | DAC 誤差のキャリブレーション |
lowpassResample | エイリアス除去リサンプリング |
interpExtrap | 複数信号の補間 |
laplace2sos | ラプラスからバイクアッド SOS への変換 |
ac0Reader | HSpice AC データのインポート |
tr0Reader | HSpice 過渡データのインポート |
sw0Reader | HSpice DC スイープデータのインポート |
注意点(MSB 固有)
- W1:
Fsは推測で決めず、データから常に計算してください(1/median(diff(x)))。 - W2:位相雑音を測定する場合、RBW は最小オフセット周波数の半分以下にしてください。
- W3:時間領域の電圧データ(MSB のシミュレーション出力)では、必ず
Type='Time'を指定してください。有効なタイプは'Frequency'(デフォルト)と'Time'のみです。 - W4:不均一にサンプリングされたデータは、まず
lowpassResampleを使って等間隔のグリッドにリサンプリングしてください。 - W5:
clockJitterMeasureには、データから推定した値ではなく、設計仕様の公称クロック周波数が必要です。 - W6:HSpice リーダーは .mat ファイルを出力します。変換後に読み込んでください。
- W7:MSB は可変ステップの離散ソルバーを使用するため、時間データは不均一になります。電圧ベースの FFT 手法は失敗するため、常に
phaseNoiseMeasure(..., Type='Time')を使用してください。この関数は内部でゼロクロッシングから位相を抽出します。 - W8:ゼロクロッシングを使う
phaseNoiseMeasureでは、中心周波数が f_carrier/2 として表示されます。これは表示上の規則であり、搬送波の値は正しいままです。 - W9:シミュレーション時間は測定可能な最小オフセット周波数を制限します。
10/f_offset_min秒以上が必要です。たとえば、10 kHz のオフセットには 1 ms 以上のシミュレーション時間が必要です。 - W10:PN プロファイルのリップルは、RBW を小さくするか、シミュレーション時間を長くすると低減します。
SpectralAveragesはset_paramで設定する PLL Testbench ブロックのパラメーターであり、phaseNoiseMeasureの引数ではありません。 - W11:MSB の可変ステップデータでは、
max(dt)/min(dt) >> 1になります。これは想定どおりです。PN にはType='Time'を使用するか、FFT 用にlowpassResampleで等間隔のグリッドを作成してください。 - W12:しきい値が信号と交差しない場合、
clockJitterMeasureは NaN を返します。(max(y)+min(y))/2または既知のロジックしきい値を使用してください。 - W13:
freqAxis(1)==0の場合、phaseNoiseToJitterは Inf を返します。呼び出す前に、必ず DC ビンを除外してください。 - W14:MSB シミュレーションデータにヒストグラムベースの DNL を絶対に使用しないでください。MSB の出力は均一なランプではないため、ヒストグラム法では誤差が 1000 倍以上になります。遷移検出を使う
inldnl(Analog, Digital, Range, Type)を必ず使用してください。 - W15:ADC には
FitMode='transitions'(デフォルト)を使用してください。DAC にはFitMode='centers'を使用してください。誤ったフィットモードを使うと、INL の結果が損なわれます。 - W16:すべての MSB 測定関数(
lockTimeMeasure、clockJitterMeasure、phaseNoiseMeasureの Type='Time')は 列ベクトルを想定しています。正しい形状にするにはx(:)とy(:)を使用してください。行ベクトルを使うと、誤った結果が通知なく返されたり、エラーが発生したりします。
著作権 2026 The MathWorks, Inc.