Generated banner for Matlab Model Serdes Systems
Generated logo for Matlab Model Serdes Systems

Matlab Model Serdes Systems

MathWorksOfficialCreated by MathWorks

  • Skill
  • Tool integration
  • Science and research
  • BSD-2-Clause
  • No issues found

From the author

Model, simulate, and optimize Serializer/Deserializer (SerDes) systems — serial and parallel links — using MATLAB SerDes Toolbox. Design NRZ and PAM-N links (PAM3 through PAM16) — explore equalization architectures (FFE, CTLE, DFE), sweep or optimize parameters with genetic algorithms, and characterize channels from loss models, S-parameter files, or crosstalk scenarios. Process captured waveforms through equalization chains, build eye diagrams, and decompose jitter. Deliver IBIS-AMI models for Tx, Rx, Redriver, or Retimer by exporting to Simulink and compiling .ami/.ibs/.dll/.so files. Covers the full arc from initial design exploration and parameter optimization to compliance testing and compiled model validation, including custom datapath blocks for nonstandard equalization.
— the description by MathWorks

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a comprehensive framework for designing and validating Serializer/Deserializer (SerDes) systems. It covers the full development lifecycle, from initial architecture exploration and channel characterization to parameter optimization and the generation of industry-standard IBIS-AMI models. Users can simulate NRZ and PAM-N links, evaluate equalization architectures like FFE, CTLE, and DFE, and perform compliance testing using statistical and time-domain analysis.

What it does

  • Models and simulates high-speed serial and parallel links including NRZ and PAM-N signaling.
  • Characterizes channels using loss models, S-parameter files, and crosstalk scenarios.
  • Optimizes equalization architectures such as FFE, CTLE, and DFE using genetic algorithms.
  • Performs statistical and time-domain analysis including eye diagrams and jitter decomposition.
  • Exports designs to Simulink for IBIS-AMI model generation and compilation.
  • Validates compiled models against behavioral baselines for compliance and performance.

When to use it

  • When designing SerDes links for specific data rates and channel loss profiles.
  • When evaluating and tuning equalization architectures to meet signal integrity targets.
  • When you need to generate IBIS-AMI models for Tx, Rx, Redriver, or Retimer components.
  • When performing compliance checks using eye masks and jitter budgets.
  • When analyzing captured waveforms from oscilloscopes or simulations.

Advantages

  • Full-arc workflow from design exploration to compiled model delivery.
  • Supports advanced PAM-N modulation schemes up to PAM16.
  • Enables programmatic parameter sweeps and optimization for design space exploration.
  • Provides robust validation tools to ensure compiled models match behavioral references.
  • Integrates seamlessly with Simulink for complex time-domain system simulations.

Usage examples

“Create a SerdesSystem object for a PAM4 link and run a statistical analysis.”
The agent initializes a SerdesSystem with specified Tx/Rx blocks, configures the channel, and executes the analysis() method to generate eye diagrams and performance metrics.
“Export my current SerDes design to a Simulink model for AMI generation.”
The agent uses exportToSimulink(sys) to generate the Simulink representation and prepares the IbisAmiManager settings for model compilation.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/matlab/matlab-model-serdes-systems/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip matlab-model-serdes-systems.zip -d .agents/skills

Documentation by MathWorks

Modeling and Simulating SerDes Systems

Design, analyze, and deliver high-speed serial link models using SerDes Toolbox. From architecture exploration through IBIS-AMI model generation, covers the full workflow for NRZ and PAM-N links (PAM3 through PAM16).

When to Use

System design and architecture exploration

  • Designing SerDes links for a target data rate, signaling scheme (NRZ, PAM4, PAM-N), and channel loss

  • Evaluating equalization architectures (FFE, CTLE, DFE) and optimizing tap settings

  • Sweeping design parameters to find optimal configurations

  • Using industry reference designs (PCIe, USB4, DDR5, CEI, UCIe) as starting points

  • Characterizing Tx/Rx analog effects (parasitic capacitance, rise time, termination impedance)

  • Building custom datapath blocks for nonstandard equalization

Channel modeling and characterization

  • Loading S-parameter Touchstone files into SerdesSystem

  • Modeling channels with loss profiles, crosstalk (FEXT/NEXT), and aggressors

  • Fitting CTLE transfer functions from measured data via ctlefit

IBIS-AMI model generation

  • Building IBIS-AMI models for Tx, Rx, Redriver, or Retimer configurations

  • Exporting to Simulink, configuring AMI parameters, and compiling .ami/.ibs/.dll/.so

  • Scripting Simulink simulations and parameter sweeps with sim/parsim

Analysis and validation

  • Running statistical and time-domain simulations

  • Processing eye diagrams (eye height, eye width, COM, VEC, bathtub curves)

  • Decomposing jitter (TJ, RJ, DJ, DDJ, DCD, ISI)

  • Validating compiled AMI models against behavioral baselines

  • Running compliance checks with eye masks and jitter budgets

When NOT to Use

  • RF/microwave circuit design, antenna modeling, or baseband DSP filter design

  • General Simulink model scripting unrelated to SerDes

Must-Follow Rules

System Setup
  • SymbolTime / SampleInterval must yield an integer SamplesPerSymbol — fractional ratios cause silent errors

  • TxModel/RxModel are Transmitter/Receiver objects — not cell arrays. Construct with Transmitter('Blocks', {block1, block2}). Transmitter requires single-quoted property names — Transmitter("Blocks", ...) throws an ismember error. Receiver and all other classes accept double quotes

  • Signal conversion functions require column vectors — impulse2pulse, pulse2stateye, etc. error on row vectors

  • Include AnalogModel and JitterAndNoise for realistic results — bare Transmitter/Receiver without analog models produce optimistic COM (1-2 dB higher). See reference/equalization-tuning.md for parameter guidance (rise time, parasitic C, termination R)

Equalization
  • Set WaveType explicitly when using datapath blocks directly in MATLAB — Simulink sets this automatically, but MATLAB defaults to "Sample"

  • Adapted DFE/CTLE parameters are in results.outparams — NOT on the block object. After analysis(), sys.RxModel.Blocks{k}.TapWeights still holds initial values. In system objects chains, adapted taps are the second output: [y, taps] = dfecdr(x)

  • DFECDR Mode=0 is passthrough in Sample mode — DFE only applies with Mode≥1. Pre-load adapted taps from outparams with Mode=1 for instant convergence, or use Mode=2 with 10x EqualizationGain (9.6e-04) for self-converging chains

  • Set Modulation on DFECDR for PAM-N in system objects chains — Simulink inherits it from the model workspace, but MATLAB defaults to 2 (NRZ). Without this, PAM4 DFE adaptation fails silently

Metrics and Waveforms
  • Metrics.summary.EW is in picoseconds (already scaled) — do NOT multiply by 1e12. EH is in volts. PAM-N returns N-1 values per metric (e.g., PAM4 → 3 eyes, PAM8 → 7 eyes)

  • Channel impulse from analysis() is in V/s — when using filter() for time-domain convolution, multiply by dt: filter(impulse * dt, 1, wave). Without scaling, amplitudes blow up by ~10^11

  • pulse2wave operates on the stimulus provided — the output modulation depends on the input pattern (NRZ or PAM-N)

  • Init-Only models cannot adapt — if DFE taps or CDR converge at runtime, you need a Dual model (both Init and GetWave)

  • AMI validation requires Signal Integrity Toolbox — serdes.AMI runner and the AMI Simulink block need both SerDes Toolbox and Signal Integrity Toolbox

  • AMI GetWave: call in a chunked loop — serdes.AMI passes BlockSize (default 1024) to AMI_GetWave, so only BlockSize samples are processed per call. You must call the object in a for loop with BlockSize-length chunks. State is preserved between calls via the DLL memory handle

  • AMI GetWave: set SkipFirstBlock = false when calling from MATLAB — the default (true) is for Simulink's internal signal buffering and causes the first block to pass through unprocessed

  • AMI Init: RowSize must match impulse length — serdes.AMI crashes MATLAB (process termination, no error) if RowSize doesn't match numel(impulse)

  • AMI generation requires Simulink model — use IbisAmiManager GUI or serdes.AMIExport with export() programmatically (see Programmatic AMI Generation)

Workflow

Design Exploration

Most projects start here. The goal is to find the right equalization architecture and settings for your channel.

  1. Design — Create a SerdesSystem with Tx/Rx blocks and channel (loss model or S-parameters)

  2. Analyze — Run analysis for statistical results, plotStatEye for eye diagrams, analysisReport for metrics

  3. Sweep — Vary channel loss, FFE taps, CTLE gain, DFE taps, or jitter to map the design space

  4. Compare — Evaluate architectures (FFE-only vs FFE+CTLE vs FFE+CTLE+DFE) using COM, eye height, eye width

  5. Select — Choose the configuration that meets margin targets, then freeze equalization settings

Use SerdesSystem for programmatic exploration; serdesDesigner for interactive GUI work.

Waveform Processing

When you have a captured or imported waveform (e.g., from an oscilloscope or simulation) and want to equalize and analyze it directly:

  1. Load — Import the waveform and define timing (SampleInterval, SymbolTime)

  2. Equalize — Stream through datapath blocks (FFE, CTLE, DFECDR) with WaveType = "Sample"

  3. Analyze — Build an eye diagram with eyeDiagramSI, extract metrics (eye height, COM, VEC)

  4. Decompose jitter — Run jitter() on the equalized waveform for TJ, RJ, DJ, DDJ, ISI breakdown

DFECDR and DFE require a sample-by-sample for loop in Sample mode; FFE and CTLE accept full vectors. See reference/waveform-processing.md for the Direct Equalization pattern.

IBIS-AMI Model Delivery

When you need compiled models (.ami/.ibs/.dll/.so) for EDA tools or IP delivery:

  1. Export — Call exportToSimulink(sys) to generate a Simulink model from the frozen design

  2. Configure — Set AMI parameters, IBIS component/pin data, and model type via IbisAmiManager or serdes.AMIExport

  3. Generate — Build .ami/.ibs and compile .dll/.so via serdes.AMIExport with export()

  4. Validate — Load compiled DLL/SO with serdes.AMI, compare against behavioral reference (Init for impulse, GetWave for waveform)

  5. Cross-check — The Simulink path (sim with Rx WaveOut) is the preferred time-domain reference. Compare against: statistical analysis(), system objects direct chain, and compiled AMI DLLs. See reference/simulink-serdes-simulation.md

  6. Iterate — Fix discrepancies, re-export, re-validate until all paths agree

AMI Model Types

Choose the model type based on which equalization blocks need to adapt at runtime:

TypeInit_Returns_ImpulseGetWave_ExistsUse For
Init-OnlytruefalseLTI equalization (fixed FFE, CTLE). Supports statistical analysis
GetWave-OnlyfalsetrueTime-domain only. No statistical analysis
DualtruetrueAdaptive equalization (DFE, CDR). All analysis types

Every IBIS-AMI model implements AMI_Init (required), AMI_GetWave (optional), and AMI_Close (required) per the IBIS standard.

Key Classes

ClassPurpose
SerdesSystemTop-level system. Methods: analysis, plotStatEye, plotImpulse, plotPulse, plotAlignedPulse, plotWavePattern, analysisReport, exportToSimulink
TransmitterTx container. Construct: Transmitter('Blocks', {serdes.FFE(...)})
ReceiverRx container. Construct: Receiver('Blocks', {serdes.CTLE(...), serdes.DFECDR(...)})
ChannelDataChannel spec. Props: ChannelLossdB, ChannelLossFreq (default 5 GHz — must override to Nyquist), ChannelDifferentialImpedance, or Impulse/dt
JitterAndNoiseIBIS 7.0 jitter/noise. 4 groups: Tx jitter (Rj/Dj/DCD/Sj), Rx jitter, Rx clock recovery (5 params, active with RxClockMode='clocked', 'convolved', or 'normal'), Rx noise. Values in seconds (default) or UI. See reference/serdes-api-reference.md
serdes.AMIRun compiled AMI DLLs/SOs. Call: [waveOut, impulseOut] = ami(waveIn, impulseIn, clockIn)
serdes.AMIExportProgrammatic AMI export (R2026a+). Methods: export, getExportSettings. Props: ModelTypeTx, DLLFiles, LinuxCrossCompile
SParameterChannelS-parameter to impulse response. Handles .s4p through .s16p (multi-port returns Nx(K) matrix: col 1=thru, cols 2+=aggressors). Props: FileName, SampleInterval, StopTime, PortOrder
eyeDiagramSIWaveform eye diagram (R2024a+). Step: eyeObj(wave) — no output. Metrics: eyeHeight, eyeWidth, com, vec, margin
ctlefitCTLE pole/zero fitter. Import: ctlefit.readcsv. Output: GPZ matrix for serdes.CTLE("Specification", "GPZ Matrix")
Datapath Blocks
BlockRoleMode ValuesKey Properties
serdes.FFEFeed-forward equalizer0, 1TapWeights, TapSpacing, Normalize
serdes.CTLEContinuous-time linear EQ0, 1, 2Specification, DCGain, ACGain, PeakingGain, GPZ
serdes.DFECDRDFE + clock recovery0, 1, 2TapWeights, CDRMode, PhaseDetector, Count
serdes.DFEStandalone DFE0, 1, 2TapWeights, EqualizationGain, EqualizationStep
serdes.CDRStandalone CDR0, 1CDRMode, Count, Step, Sensitivity. Mode is deprecated
serdes.AGCAuto gain control0, 1TargetRMSVoltage, MaxGain, AveragingLength
serdes.VGAVariable gain amplifier0, 1Gain
serdes.SaturatingAmplifierLimiting amplifier0, 1Limit, LinearGain, Specification
serdes.PassThroughNo-op placeholder——

Mode values: 0 = Fixed (not exported), 1 = Fixed (exported as AMI parameter), 2 = Adaptive (GetWave). Only CTLE, DFECDR, and DFE support Mode=2.

Set CTLE Specification before setting gain properties — using ACGain with the default spec triggers a warning. GPZ Matrix requires Mode=1 for ConfigSelect to switch rows. See reference/equalization-tuning.md for the 4 specification options.

Patterns

Each reference file includes executable code patterns for its topic. Load the relevant reference before writing code — it contains correct calling conventions, constructor arguments, and property names. See the References table in Conventions below for the full routing map.

Common Mistakes

See reference/common-mistakes.md for 37 documented anti-patterns with wrong/correct code pairs covering API misuse, wrong property names, silent failures, and performance pitfalls.

Conventions

Design
  • Use SerdesSystem for programmatic design; serdesDesigner for interactive exploration. Always run analysis/plotStatEye before exporting

  • CRITICAL: ChannelLossFreq defaults to 5 GHz — always override to Nyquist (1/(2*SymbolTime)). Without this, 15 dB at 5 GHz becomes 40+ dB at Nyquist and the eye appears closed. Use SParameterChannel for real channels

  • analysis() does not auto-optimize FFE taps — use canonical de-emphasis with sum(abs(taps)) ≈ 1.0

  • DFE taps initialized to zero are optimized by the statistical solver automatically

  • Industry reference designs: serdesDesigner or openExample('serdes/PCIe5TransmitterReceiverIBISAMIModelExample'). See reference/equalization-tuning.md for starting-point configurations

Visualization and Metrics
  • All SerdesSystem plot methods (plotStatEye, plotImpulse, plotPulse, plotAlignedPulse, plotWavePattern) render into the current axes — use tiledlayout/nexttile or subplot for multi-panel layouts

  • eyeDiagramSI (R2024a+) for waveform eye diagrams; jitter (R2024b+) for jitter decomposition

  • DFECDR/DFE in "Sample" WaveType require scalar (sample-by-sample) input; FFE/CTLE accept full vectors

  • When generating PRBS waveforms via pulse2wave, ask the user for PRBS order and symbol count — default PRBS-10 (1023 symbols) if unspecified

  • Use serdes.utilities.SignalIntegrityColorMap (not hot/parula) for pulse2stateye plots. For compliance, use margin(eyeObj, eyeMask)

  • See reference/visualization-and-metrics.md for all plot methods, metrics fields/units, eyeDiagramSI, and jitter

AMI Export and Validation
  • Use serdes.AMIExport with export() for programmatic AMI generation — not slbuild (legacy, R2025b and earlier only)

  • Validate compiled DLLs/SOs with serdes.AMI before sending to EDA tools — both Init (impulse correlation) and GetWave (waveform chain)

  • Simulink is the preferred time-domain path — sim() with Rx WaveOut is the ground truth for adaptive systems. Compare against system objects chain and compiled AMI DLLs as cross-checks. Use the same PRBS stimulus across all time-domain paths

  • AMI export parameters on Simulink blocks use *AMI suffix ('ModeAMI', 'TapWeightsAMI'); model-level settings go through IbisAmiManager or serdes.AMIExport

  • No compiled DLLs/SOs ship with the toolbox. Cross-compile for Linux .so via serdes.utilities.createCrossCompiler

Script-First Workflow

For design, analysis, or sweep tasks — write code to .m files on disk, not inline MCP snippets. For quick one-off checks, inline evaluate_matlab_code is fine.

  1. Create a .m file (e.g., serdes_pam4_design.m), run via run_matlab_file, iterate by editing and re-running

  2. Deliver a polished script — %% Parameters block at top, %% Section headers, summary fprintf at end

References
Load when...Reference
Building or modifying a SerdesSystemreference/serdes-api-reference.md
Debugging wrong API names or silent failuresreference/common-mistakes.md
Working with S-parameter files or crosstalkreference/channel-modeling.md
Tuning CTLE, FFE, DFE, or fitting transfer functionsreference/equalization-tuning.md
Sweeping parameters or running GA optimizationreference/optimization.md
Plotting eyes, reading metrics, or decomposing jitterreference/visualization-and-metrics.md
Equalizing captured or imported waveforms directlyreference/waveform-processing.md
Exporting to Simulink, compiling AMI DLLs, or validating AMI modelsreference/programmatic-ami-generation.md
Scripting Simulink simulations or parsim sweepsreference/simulink-serdes-simulation.md
Building custom datapath blocksreference/custom-datapath-blocks.md
Looking up utility functions (SNR, ICN, resample)reference/serdes-utilities.md

Files

reference/visualization-and-metrics.md

Visualization and Metrics

Plot methods, metrics extraction, eye diagram analysis, and jitter decomposition for SerDes systems. Covers both statistical (analysis() path) and time-domain (eyeDiagramSI path) workflows.

SerdesSystem Plot Methods

All plot methods render into the current axes. They work with subplot, tiledlayout/nexttile, or standalone figure. All auto-call analysis() if needed — no prerequisite.

MethodWhat It ShowsX-AxisTraces
plotStatEye(sys)Statistical eye heatmap + contourspsImage + N-1 eye contour pairs (PAM-N)
plotImpulse(sys)Impulse responsensUnequalized + Equalized (+ FEXT/NEXT with crosstalk)
plotPulse(sys)Pulse responsensUnequalized + Equalized
plotAlignedPulse(sys)Pulse aligned to cursorUIUnequalized + Equalized
plotWavePattern(sys)PRBS waveformnsUnequalized + Equalized
analysisReport(sys)Text summary to command window—Not a figure — prints EH/EW/COM/VEC + adapted params
Multi-Panel Layouts
% tiledlayout — preferred for multi-panel
figure; tiledlayout(1, 2);
nexttile; plotStatEye(sysA); title("Config A");
nexttile; plotStatEye(sysB); title("Config B");
sgtitle("Side-by-Side Comparison");

% subplot works too
figure;
subplot(1, 2, 1); plotStatEye(sysA); title("Config A");
subplot(1, 2, 2); plotStatEye(sysB); title("Config B");

% All plot methods work the same way
figure; tiledlayout(2, 2);
nexttile; plotImpulse(sys);      title("Impulse");
nexttile; plotPulse(sys);        title("Pulse");
nexttile; plotAlignedPulse(sys); title("Aligned Pulse (UI)");
nexttile; plotWavePattern(sys);  title("PRBS Waveform");
Crosstalk Traces

With crosstalk enabled (ICN or multi-port S-parameters), plotImpulse adds FEXT and NEXT traces automatically — 6 traces total:

  • Unequalized primary, Equalized primary

  • Unequalized FEXT, Equalized FEXT

  • Unequalized NEXT, Equalized NEXT

Other plot methods show only primary (victim) traces.

Metrics from analysis()

After analysis(sys), metrics are on sys.Metrics.summary:

FieldUnitNotes
COMestimatedBChannel Operating Margin
EHvoltsEye Height — multiply by 1e3 for mV
EWpicosecondsEye Width — already scaled, do NOT multiply by 1e12
VECpercentVertical Eye Closure
eyeLinearityratio1.0 = ideal (PAM4+)

PAM-N returns N-1 values per metric (e.g., PAM4 returns 3 EH values, one per eye). Index with EH(2) for the center (worst) eye.

results = analysis(sys);
m = sys.Metrics.summary;
fprintf("COM: %.2f dB, EH: %.1f mV, EW: %.1f ps\n", ...
    m.COMestimate, m.EH(2)*1e3, m.EW(2));
analysisReport Output

analysisReport(sys) prints a formatted text summary to the command window:

  • Eye Height/Width/Area per eye (Upper, Center, Lower for PAM4)

  • COM, VEC, eyeLinearity

  • Adapted parameter values (CTLE ConfigSelect, DFE TapWeights, CDR Phase)

  • Interior DFE state (thresholds, counters, frequency estimates)

optPulseMetric (LTI Only)

Computes metrics from the equalized pulse response — no jitter, no noise. Use for quick LTI design exploration; use sys.Metrics.summary for jitter-aware metrics.

results = analysis(sys);
eqPulse = results.pulse(:, 2);  % column 2 = equalized
metrics = optPulseMetric(eqPulse, samplesPerSymbol, sampleInterval, targetBER);
fprintf("COM: %.1f dB, EH: %.1f mV, EW: %.1f ps\n", ...
    metrics.maxCOM, metrics.maxEyeHeight * 1e3, metrics.eyeWidth * 1e12);

eyeDiagramSI (R2024a+)

System object that builds a 2-D eye histogram from time-domain waveform data. Provides measurement methods for eye metrics, bathtub curves, and compliance testing.

Setup and Usage
eyeObj = eyeDiagramSI;
eyeObj.SampleInterval = dt;       % sample interval (seconds)
eyeObj.SymbolTime = symbolTime;   % symbol period (seconds)
eyeObj.Modulation = modulation;   % 2 = NRZ, 4 = PAM4, etc.
eyeObj(waveform);                 % step — NO output capture

Critical: Do NOT name the variable eye — it shadows MATLAB's built-in eye() matrix function. Use eyeObj instead.

The step call has no output argument. It updates internal state (histogram). Capturing the output errors:

% WRONG — stepImpl has no output
result = eyeObj(waveform);  % ERROR: Too many output arguments

% CORRECT — call without output, then read metrics
eyeObj(waveform);
eh = eyeHeight(eyeObj);
Properties
PropertyDefaultDescription
SampleInterval1Time between samples (seconds)
SymbolTime8Symbol period (seconds)
Modulation2Number of symbol levels
ClockMode"Auto"Clock recovery: "Auto", "Clocked", "Ideal", "Convolved"
PhaseDetector"BangBang"CDR algorithm: "BangBang", "BaudRateTypeA", "None"
SymbolsPerDiagram2Eye width in symbol periods
TimeBins255Histogram time resolution
AmplitudeBins255Histogram voltage resolution
AmplitudeLimits[]Voltage range [min max] — auto if empty
SymbolThresholds[]Decision thresholds — auto for PAM4
Measurement Methods
MethodReturnsDescription
eyeHeight(eye)scalar or vectorVertical eye opening (V). PAM-N returns N-1 values
eyeWidth(eye)scalar or vectorHorizontal eye opening (seconds)
eyeArea(eye)scalar or vectorArea of eye opening (V*s)
com(eye)scalarChannel operating margin (dB)
vec(eye)scalarVertical eye closure (dB) — 20*log10(amplitude/eyeHeight). Note: different unit than Metrics.summary.VEC (percent)
eyeLinearity(eye)scalarPAM4 eye linearity (1.0 = ideal)
risetime(eye)scalarRise time from eye diagram
falltime(eye)scalarFall time from eye diagram
eyeCenter(eye)structCenter point coordinates
eyeCrossing(eye)structCrossing point coordinates
eyeAmplitude(eye)scalarPeak-to-peak eye amplitude
eyeLevels(eye)structSymbol level statistics
margin(eye, mask)structCompliance margin against eyeMask
bathtub(eye)—Plot bathtub curves
slice(eye, ...)vectorExtract histogram slice
Plotting
figure;
plot(eyeObj);                  % 2-D eye diagram with colormap
title("Eye Diagram Title");   % title() works on the axes
eyeDiagramSI vs pulse2stateye
FeatureeyeDiagramSIpulse2stateye
InputTime-domain waveformPulse response (column vector)
MethodHistogram accumulationStatistical convolution
JitterCaptured from waveformNot included (LTI only)
Clock recoveryBuilt-in CDRNone
StreamingCan call step() multiple timesSingle call
MetricsRich method set (COM, VEC, margins)Use optPulseMetric separately
Compliancemargin() with eyeMaskManual
Best forPost-equalization waveform analysisQuick LTI design exploration

Custom Statistical Eye Rendering

Use pulse2stateye to build a statistical eye matrix for custom visualization:

results = analysis(sys);
eqPulse = results.pulse(:, 2);
[statEye, vAxis, tAxis] = pulse2stateye(eqPulse, samplesPerSymbol, modulation);

figure;
imagesc(tAxis * 1e12, vAxis * 1e3, statEye);
colormap(serdes.utilities.SignalIntegrityColorMap);
colorbar;
axis xy;
xlabel("Time (ps)"); ylabel("Voltage (mV)");
title("Statistical Eye");

Colormap convention: Use serdes.utilities.SignalIntegrityColorMap (not hot or parula) for statistical eye plots. Always add colorbar.

jitter (R2024b+)

Function that decomposes jitter from time-domain waveforms into standard IBIS/JEDEC jitter components.

Basic Usage
% With SampleInterval and SymbolTime (suppress plots for scripting)
J = jitter(waveform, SampleInterval=dt, SymbolTime=symbolTime, Plot=false);

% With explicit time vector
J = jitter(timeVec, waveform, SymbolTime=symbolTime, Plot=false);

% With reference waveform (for ISI separation) — plots enabled
J = jitter(timeVec, waveform, timeRef, waveRef, Plot="on");
Built-In Jitter Plots

When Plot=true (default) or Plot="on", jitter() creates a 7-panel figure showing PDF histograms for each jitter component: TJ, RJ, DJ, SJ, DDJ, DCD, ISI. Each panel shows timing error on the x-axis and PDF estimate on the y-axis.

Set Plot=false in scripts to suppress automatic histogram figures. When running in automated pipelines or MCP evaluation, always use Plot=false to avoid unwanted figure windows.

Output Structure Fields
FieldUnitDescription
TJrmssecondsTotal jitter (RMS)
TJpkpksecondsTotal jitter (peak-to-peak)
RJrmssecondsRandom jitter (RMS)
DJrmssecondsDeterministic jitter (RMS)
DJpkpksecondsDeterministic jitter (peak-to-peak)
DDJrmssecondsData-dependent jitter (RMS)
DDJpkpksecondsData-dependent jitter (peak-to-peak)
DCDrmssecondsDuty cycle distortion (RMS)
DCDpkpksecondsDuty cycle distortion (peak-to-peak)
ISIrmssecondsInter-symbol interference jitter (RMS)
ISIpkpksecondsInter-symbol interference jitter (peak-to-peak)
SJasecondsSinusoidal jitter amplitude
SJfHzSinusoidal jitter frequency
SJpradiansSinusoidal jitter phase

Critical: Field names use rms/pkpk suffixes — not plain TJ, RJ, etc.

Name-Value Options
NameDefaultDescription
SampleInterval—Sample period for uniformly sampled data
SymbolTime—Symbol period
SymbolThresholdsautoDecision thresholds for edge detection
PlottrueDisplay jitter histogram plots
Frequencies1Max sinusoidal jitter frequencies to detect
PastSymbols31Symbols before edge for DDJ correlation
FutureSymbolsautoSymbols after edge for DDJ correlation
DCDMethod"oddeven"DCD measurement: "oddeven" or "risefall"
Sinusoidal Jitter Detection Limitation

The jitter() function's sinusoidal jitter (SJ) detection works best with a single dominant SJ frequency. When multiple SJ frequencies are present, set Frequencies to the expected count. With no sinusoidal jitter present, the detected SJa may be nonzero but small — treat values below 0.01 UI as noise floor artifacts.

PRBS Waveform Generation

When generating time-domain waveforms via pulse2wave, the PRBS order and symbol count are user-configurable. Default to PRBS-10 (1023 symbols) if unspecified, but always offer the choice. Longer sequences improve jitter statistics but increase computation time.

prbsOrder = 10;
nSymbols = 2^prbsOrder - 1;  % 1023 symbols
prbsSeq = prbs(prbsOrder, nSymbols * samplesPerSymbol);
wave = pulse2wave(eqPulse, prbsSeq, samplesPerSymbol);

When comparing across multiple analysis paths (statistical, Simulink sim(), system objects chain, AMI DLL chain), use the same PRBS sequence and length so results are directly comparable.

Compliance Testing

Use eyeMask with eyeDiagramSI.margin() for standards-based pass/fail testing:

% Create eye mask for compliance testing
mask = eyeMask;
mask.MaskType = "Hexagonal";                  % or "Rectangular"
mask.EyeHeightThreshold = 15e-3;              % 15 mV minimum eye opening
mask.EyeWidthThreshold = 0.3;                 % 0.3 UI minimum width
mask.SymbolTime = symbolTime;

% Run margin check against the mask
result = margin(eyeObj, mask);
fprintf("Margin: %.2f dB, Pass: %s\n", result.Margin, string(result.Pass));

eyeMask defines the compliance region. margin() returns the distance (in dB) to the mask boundary. Positive margin = pass; negative = fail.

For CDR jitter tolerance (JTOL) compliance testing, see the Simulink-based simulinkJTOLController workflow (requires Simulink + Parallel Computing Toolbox).

Bathtub Curves

Bathtub curves show BER vs timing offset — the horizontal eye margin at each BER level.

% Generate bathtub curve from eyeDiagramSI
figure;
bathtub(eyeObj);
title("Bathtub Curve");

bathtub(eyeObj) plots the bathtub curve directly. The curve shows BER on a log scale (y-axis) vs timing offset in UI (x-axis), with the characteristic bathtub shape where the minimum BER corresponds to the optimal sampling point.

COM Waterfall (Per-Stage Contribution)

To understand how each equalization stage contributes to COM, run analysis with progressively more EQ stages enabled:

% Build configurations with increasing equalization
configs = {
    "Channel only",    {serdes.PassThrough},                  {};
    "FFE only",        {ffe},                                {};
    "FFE+CTLE",        {ffe},                                {ctle};
    "FFE+CTLE+DFE",    {ffe},                                {ctle, dfecdr};
};
comValues = zeros(size(configs, 1), 1);

for k = 1:size(configs, 1)
    sys = SerdesSystem(...
        'TxModel', Transmitter('Blocks', configs{k, 2}), ...
        'RxModel', Receiver('Blocks', configs{k, 3}), ...
        'ChannelData', channel, ...
        'SymbolTime', symbolTime, 'SamplesPerSymbol', 16, ...
        'Modulation', modulation, 'BERtarget', 1e-6);
    sys.ChannelData.ChannelLossFreq = 1 / (2 * symbolTime);
    analysis(sys);
    comValues(k) = sys.Metrics.summary.COMestimate;
end

% Plot waterfall
figure;
bar(comValues);
set(gca, "XTickLabel", configs(:, 1));
ylabel("COM (dB)"); title("EQ Stage Contribution");

This reveals which stage provides the most margin improvement and whether any stage is counterproductive (e.g., CTLE at low loss or with PAM8+).

Advanced Visualization Patterns

3D Surface Plot (COM vs Two Parameters)

Visualize COM across a 2-D parameter sweep as a 3D surface:

% Sweep FFE pre-cursor and CTLE AC gain
preRange = -0.20:0.02:0;
acRange = 0:2:20;
comSurf = zeros(numel(acRange), numel(preRange));

for i = 1:numel(acRange)
    for j = 1:numel(preRange)
        pre = preRange(j);
        main = 1 - abs(pre) - 0.15;  % post fixed at -0.15
        ffe = serdes.FFE("TapWeights", [pre main -0.15]);
        ctle = serdes.CTLE("Specification", "DC Gain and AC Gain", ...
            "DCGain", 0, "ACGain", acRange(i));
        sysT = SerdesSystem('ChannelData', channel, ...
            'TxModel', Transmitter('Blocks', {ffe}), ...
            'RxModel', Receiver('Blocks', {ctle, dfecdr}), ...
            'SymbolTime', symbolTime, 'SamplesPerSymbol', 16, ...
            'Modulation', modulation);
        sysT.ChannelData.ChannelLossFreq = 1 / (2 * symbolTime);
        analysis(sysT);
        comSurf(i, j) = sysT.Metrics.summary.COMestimate;
    end
end

figure;
surf(preRange, acRange, comSurf);
xlabel("FFE Pre-Cursor"); ylabel("CTLE AC Gain (dB)"); zlabel("COM (dB)");
title("COM Surface: FFE Pre vs CTLE AC Gain");
colormap(turbo); colorbar;
BER Contour Overlay on Eye Diagram

Overlay BER contour lines on an eye diagram using eyeDiagramSI:

% Build eye diagram
eyeObj = eyeDiagramSI;
eyeObj.SampleInterval = dt;
eyeObj.SymbolTime = symbolTime;
eyeObj.Modulation = modulation;
eyeObj(waveform);

% Plot with BER contours
figure;
plot(eyeObj);
hold on;

% Extract histogram and compute BER contours
hist2d = eyeObj.EyeHistogram;
totalHits = sum(hist2d(:));
berLevels = [1e-3, 1e-6, 1e-9, 1e-12];
contour(hist2d / totalHits, berLevels, "LineWidth", 1.5);
hold off;
title("Eye Diagram with BER Contours");
DFE Tap Adaptation Trajectory

Track DFE tap convergence over time using the system objects chain:

% Setup DFECDR in adaptive mode
dfecdrAdapt = serdes.DFECDR("Mode", 2, "TapWeights", zeros(1, 5), ...
    "SymbolTime", symbolTime, "SampleInterval", dt, ...
    "Modulation", modulation, "WaveType", "Sample", ...
    "EqualizationGain", 9.6e-4);  % 10x default for faster convergence

% Stream sample-by-sample and record taps
nSamples = numel(waveform);
tapHistory = zeros(nSamples, 5);
for k = 1:nSamples
    [~, taps] = dfecdrAdapt(waveform(k));
    tapHistory(k, :) = taps;
end

% Plot adaptation trajectory
symbolIndices = (1:nSamples) / samplesPerSymbol;
figure;
plot(symbolIndices, tapHistory, "LineWidth", 1.2);
xlabel("Symbols"); ylabel("Tap Weight");
title("DFE Tap Adaptation Trajectory");
legend("Tap " + (1:5), "Location", "best");

Statistical vs Time-Domain COM Discrepancy

Statistical COM (sys.Metrics.summary.COMestimate) and time-domain COM (com(eyeObj)) measure the same concept but differ in methodology:

SourceMethodIncludes
sys.Metrics.summary.COMestimateStatistical convolution of pulse responseOptimal DFE taps, BER target, jitter model
com(eyeObj)Histogram analysis of time-domain waveformActual CDR recovery, finite PRBS, waveform jitter

Expect 1-3 dB difference. Statistical COM is typically higher because it uses the optimal sampling phase and mathematically optimal DFE taps. Time-domain COM reflects real CDR tracking and finite adaptation convergence.

Use statistical COM for design-space exploration (fast, repeatable). Use time-domain COM for final validation (realistic, includes implementation effects).

Pattern: Side-by-Side Eye Comparison

% Compare two configurations side by side using tiledlayout
% plotStatEye renders into the current axes — works with subplot and tiledlayout
configs = {10, "10 dB"; 20, "20 dB"};  % {loss, label}
figure; tiledlayout(1, size(configs, 1));
for c = 1:size(configs, 1)
    sys = SerdesSystem(...
        'TxModel', Transmitter('Blocks', {serdes.FFE('TapWeights', [-0.1 0.7 -0.2])}, ...
            'AnalogModel', AnalogModel('R', 50, 'C', 1e-13), ...
            'RiseTime', 1e-11, 'VoltageSwingIdeal', 1), ...
        'RxModel', Receiver('Blocks', ...
            {serdes.CTLE('Specification', "DC Gain and AC Gain", ...
                          'DCGain', 0, 'ACGain', 12, 'PeakingFrequency', 14e9), ...
             serdes.DFECDR('TapWeights', zeros(1, 5), 'Mode', 2)}, ...
            'AnalogModel', AnalogModel('R', 50, 'C', 2e-13)), ...
        'ChannelData', ChannelData('ChannelLossdB', configs{c, 1}, ...
            'ChannelLossFreq', 14e9, 'ChannelDifferentialImpedance', 100), ...
        'JitterAndNoise', JitterAndNoise('RxClockMode', 'clocked'), ...
        'SymbolTime', 35.71e-12, 'SamplesPerSymbol', 16, ...
        'Modulation', 4, 'Signaling', 'Differential', 'BERtarget', 1e-6);
    results = analysis(sys);
    m = sys.Metrics.summary;
    nexttile; plotStatEye(sys);
    title(sprintf("%s — COM %.1f dB, EH %.1f mV", configs{c, 2}, m.COMestimate, m.EH(2)*1e3));
    for p = 1:numel(results.outparams)
        if isstruct(results.outparams{p}) && isfield(results.outparams{p}, 'DFECDR')
            fprintf("%s DFE taps: %s\n", configs{c, 2}, mat2str(results.outparams{p}.DFECDR.TapWeights, 3));
        end
    end
end

All SerdesSystem plot methods (plotStatEye, plotImpulse, plotPulse, plotAlignedPulse, plotWavePattern) render into the current axes. Use tiledlayout/nexttile or subplot for multi-panel layouts.

Pattern: Waveform Eye Diagram and Jitter Analysis

% Build eye diagram from time-domain waveform (R2024a+)
eyeObj = eyeDiagramSI;
eyeObj.SampleInterval = dt;
eyeObj.SymbolTime = symbolTime;
eyeObj.Modulation = modulation;
eyeObj(waveform);  % step — NO output capture

% Read metrics
eh = eyeHeight(eyeObj);    % PAM-N returns N-1 values (one per eye)
ew = eyeWidth(eyeObj);
comVal = com(eyeObj);
fprintf("Eye Height: %.1f mV, Eye Width: %.1f ps, COM: %.2f dB\n", ...
    eh(1) * 1e3, ew(1) * 1e12, comVal);

% Jitter decomposition (R2024b+)
% Requires a long waveform (>200 symbols) — use pulse2wave with PRBS-10+
prbsSeq = prbs(10, (2^10 - 1) * samplesPerSymbol);
wave = pulse2wave(eqPulse, prbsSeq, samplesPerSymbol);
J = jitter(wave, SampleInterval=dt, SymbolTime=symbolTime, Plot=false);
fprintf("TJ: %.2f ps (pk-pk), RJ: %.2f ps (RMS), DDJ: %.2f ps (pk-pk)\n", ...
    J.TJpkpk * 1e12, J.RJrms * 1e12, J.DDJpkpk * 1e12);

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
MathWorks
Publisher
MathWorks (Official)
Source
matlab/matlab-agentic-toolkit · skills-catalog/rf-and-mixed-signal/matlab-model-serdes-systems · commit 2a7f215
Licence
BSD 2-Clause License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE.md)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by MathWorks or MathWorks.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-model-serdes-systems.zip