matlab-analyze-pcb-pdn

$npx mdskill add matlab/matlab-agentic-toolkit/matlab-analyze-pcb-pdn

Analyze PCB power distribution networks for DC voltage and current.

  • Solves power integrity issues like IR drop and current density violations.
  • Depends on imported PCB layout data from matlab-read-pcb-layout.
  • Infers nominal voltages from net names and assigns source/load topology.
  • Returns voltage/current distributions and design rule check results.

SKILL.md

.github/skills/matlab-analyze-pcb-pdnView on GitHub ↗
---
name: matlab-analyze-pcb-pdn
description: "PDN DC voltage/current analysis, IR drop, design rule checking, and multi-net batch analysis on imported PCB layouts. TRIGGER: user asks about power integrity, PDN analysis, IR drop, voltage distribution, current density, power nets, or design rule checking on a PCB. Invoke BEFORE writing code — the PDN API chain is specialized and non-obvious. SKIP: importing a PCB file (use matlab-read-pcb-layout), EM field/S-parameter extraction (use matlab-analyze-em), material/stackup setup only (use matlab-manage-pcb-material), transmission line design (use matlab-design-pcb-txline)."
license: MathWorks BSD-3-Clause
metadata:
  author: MathWorks
  version: "1.0"
---

# Analyzing Power Distribution Networks (PDN)

## When to Use

- Analyzing DC voltage and current distribution on PCB power rails
- Checking design rules (max current density, voltage margins, via current limits)
- Discovering and listing power nets on an imported PCB layout
- Assigning source/load/sense topology for PDN analysis
- Running batch analysis across multiple power rails on a board
- Inferring nominal voltage from standard PCB net naming conventions

## When NOT to Use

- Importing PCB layouts (Gerber, ODB++, Allegro) — use `matlab-read-pcb-layout`
- Analyzing S-parameters, fields, or EM performance — use `matlab-analyze-em`
- Analyzing crosstalk between signal traces — use `matlab-design-pcb-txline`
- Defining dielectric or conductor materials — use `matlab-manage-pcb-material`
- Modeling via structures — use `matlab-model-via`

## Typical Workflow

1. **Before:** `matlab-read-pcb-layout` — import the PCB layout from Gerber/ODB++/Allegro
2. **This skill:** Run DC analysis, check IR drop, evaluate design rules, batch-analyze nets
3. **After:** Iterate on the physical design in CAD and re-import, or use results to inform stackup changes via `matlab-manage-pcb-material`

## Quick Reference

| Task | Code |
|------|------|
| Import PCB layout | `pcb = pcbFileRead('board_native')` |
| List all nets | `netList = cadnetList(pcb)` |
| Find power nets | Filter `cadnetList(pcb)` with `regexpi` (see below) |
| Find specific rail | `idx = ~cellfun(@isempty, regexpi(netList.CadnetName, "P0V8"))` |
| Infer rail voltage | Parse net name with regex helper `parseNetVoltage` (see below) |
| Create cadnet | `cnet = cadnet(pcb, 'P0V8')` |
| Show cadnet layout | `show(cnet)` |
| Find components on net | `comps = findComponents(cnet)` |
| Filter by type | `inductors = findComponents(cnet, "ComponentType", "Inductor")` |
| Create PDN model | `PDN = powerDistributionNetwork(cnet)` |
| Assign topology | `setNetworkParameters(PDN, Source=src, Load=load, Sense=sense)` |
| Auto-assign topology | `setNetworkParameters(PDN, AutoAssignDefault='True')` |
| Set DC parameters | `setDCParameters(PDN, "NominalVoltage", 0.8, "LoadCurrent", 1)  % placeholder — ask user` |
| Set DC rules | `setDCRules(PDN, "MaxCurrentDensity", 0.5, "MinVoltage", 0.784)` |
| Voltage distribution | `voltage(PDN)` |
| Voltage with violations | `voltage(PDN, ShowViolation=true)` |
| Current distribution | `current(PDN)` |
| Current with arrows | `current(PDN, Direction='on')` |

## PCB Import and Net Discovery

### Importing a PCB Layout

`pcbFileRead` imports a PCB file and returns an object for hierarchical inspection. Supported formats: native directory (CSV files), ODB++ (zipped or unzipped), and Cadence Allegro `.brd` (requires one-time `extractaSetup()`).

```matlab
% Native format (directory containing CSV files)
pcb = pcbFileRead(fullfile(boardDir, 'pcie5_native'));

% ODB++ format
pcb = pcbFileRead(fullfile(boardDir, 'myboard.zip'));

% Allegro .brd (run extractaSetup() once first)
extractaSetup();  % one-time setup for Allegro support
pcb = pcbFileRead(fullfile(boardDir, 'myboard.brd'));
```

The returned object exposes: `NumLayers`, `NumCadnets`, `NumPadStacks`, `NumComponents`, `NumParts`, `LayerHeight`.

### Listing All Nets

```matlab
NetList = cadnetList(pcb);
disp(NetList);
```

Returns a table with columns: `CadnetIdx`, `CadnetName`, `NumPins`, `Length`. A real board may have 3000+ nets.

### Finding Power Nets

There is no built-in `findPowerNets` function. Filter the `cadnetList` output using regex to identify power and ground nets by name:

```matlab
netList = cadnetList(pcb);

% Define naming patterns (case-insensitive)
powerPatterns = ["^P\d+V", "^VDD", "^VCC", "^AVDD", "^DVDD", "^VDDO"];
groundPatterns = ["^GND", "^AGND", "^DGND", "^PGND", "^VSS", "^AVSS", "^DVSS"];

% Match power nets
isPower = false(height(netList), 1);
for p = powerPatterns
    isPower = isPower | ~cellfun(@isempty, regexpi(netList.CadnetName, p));
end
powerNets = sortrows(netList(isPower, :), 'NumPins', 'descend');

% Match ground nets
isGround = false(height(netList), 1);
for g = groundPatterns
    isGround = isGround | ~cellfun(@isempty, regexpi(netList.CadnetName, g));
end
groundNets = sortrows(netList(isGround, :), 'NumPins', 'descend');

% Filter by minimum pin count
minPins = 5;
powerNets = powerNets(powerNets.NumPins >= minPins, :);

% Search for a specific pattern (e.g., 0.8V rails)
idx = ~cellfun(@isempty, regexpi(powerNets.CadnetName, "P0V8"));
rails_0v8 = powerNets(idx, :);
```

**Common power net naming conventions (case-insensitive):**
- Power rails: `P<digit>V<digit>` (P0V8, P3V3_AUX, P12V), `VDD*`, `VCC*`, `AVDD*`, `DVDD*`, `VDDO*`
- Ground nets: `GND*`, `AGND*`, `DGND*`, `PGND*`, `VSS*`, `AVSS*`, `DVSS*`

### Inferring Rail Voltage from Net Name

There is no built-in `inferRailVoltage` function. Parse voltage from net names using regex:

```matlab
function nomV = parseNetVoltage(netName)
    netName = string(netName);
    % Pattern: P<int>V<frac> (e.g., P0V8 → 0.8, P3V3 → 3.3, P12V → 12.0)
    tok = regexp(netName, '(?i)P(\d+)V(\d*)', 'tokens');
    if ~isempty(tok)
        intPart = str2double(tok{1}{1});
        fracStr = tok{1}{2};
        if isempty(fracStr)
            nomV = intPart;
        else
            nomV = intPart + str2double(fracStr) / 10^numel(fracStr);
        end
        return;
    end
    % Pattern: explicit decimal (e.g., 3.3V, 1.8V)
    tok = regexp(netName, '(\d+\.\d+)\s*V', 'tokens');
    if ~isempty(tok)
        nomV = str2double(tok{1}{1});
        return;
    end
    % Pattern: millivolt (e.g., 800MV → 0.8)
    tok = regexp(netName, '(\d+)\s*MV', 'tokens', 'ignorecase');
    if ~isempty(tok)
        nomV = str2double(tok{1}{1}) / 1000;
        return;
    end
    nomV = NaN;
end
```

Usage in a loop:

```matlab
for k = 1:height(powerNets)
    netName = powerNets.CadnetName{k};
    nomV = parseNetVoltage(netName);
    fprintf('%s → %.2f V\n', netName, nomV);
end
```

## cadnet Object

### Creating a Cadnet

```matlab
cnet = cadnet(pcb, 'P0V8');
```

**Properties:**

| Property | Description |
|----------|-------------|
| `NumPins` | Number of pins on the net |
| `NumSurfaces` | Number of copper surfaces |
| `NumVias` | Number of vias |
| `NumTraces` | Number of traces |
| `TotalLength` | Total trace length |
| `EntityList` | List of all entities |
| `Voltage` | Nominal voltage |
| `LayerRange` | Layers spanned by the net |

### Visualizing a Cadnet

```matlab
show(cnet);
```

### Finding Connected Components

`findComponents` returns a table with columns: `Refdes`, `PinList`, `ComponentType`, `Part`.

```matlab
% All components on the net
allComps = findComponents(cnet);

% Filter by component type
inductors = findComponents(cnet, "ComponentType", "Inductor");
ics       = findComponents(cnet, "ComponentType", "IC");
resistors = findComponents(cnet, "ComponentType", "Resistor");
caps      = findComponents(cnet, "ComponentType", "Capacitor");
```

The `Refdes` values are strings -- use them directly for Source/Load/Sense assignment in `setNetworkParameters`.

### Getting Detailed Cadnet Data

```matlab
data = cadnetData(cnet);
s = shapes(cnet);
```

## powerDistributionNetwork Object

### Creating a PDN Model

```matlab
PDN = powerDistributionNetwork(cnet);
```

**Properties:**

| Property | Description |
|----------|-------------|
| `NetType` | Type of net |
| `Source` | Source component(s) |
| `Load` | Load component(s) |
| `Sense` | Sense component(s) |
| `PlatingThickness` | Via barrel plating thickness (inches) |
| `NominalVoltage` | Nominal voltage (V) |
| `LoadCurrent` | Load current (A) |
| `MaxCurrentDensity` | Max current density (mA/mil²) |
| `MinVoltage` | Minimum allowable voltage (V) |
| `MaxVoltage` | Maximum allowable voltage (V) |
| `MaxViaCurrent` | Max via current (mA) |

## PDN Configuration

### setNetworkParameters -- Assign Source, Load, Sense, Plating

Use `findComponents` output to assign topology:

```matlab
% Manual assignment using RefDes from findComponents
setNetworkParameters(PDN, ...
    Source=sourceRefDes, ...
    Load=sinkRefDes, ...
    Sense=senseRefDes, ...
    PlatingThickness=0.002);

% Auto-assign defaults (fallback when topology is unclear)
setNetworkParameters(PDN, AutoAssignDefault='True');
```

- **Source** -- RefDes of the power source (typically an inductor). Use all inductors for multiphase rails.
- **Load** -- RefDes of the load (typically an IC). Use all ICs on the net.
- **Sense** -- RefDes of the sense component (typically a resistor or test point).
- **PlatingThickness** -- Via barrel plating thickness in **inches** (e.g., `0.002` = 2 mil ≈ 1.4 oz copper).

#### Sense Component Resolution

The `Sense` parameter is required. When no test point is available on the net, use a resistor as the sense component:

```matlab
tp = findComponents(cnet, 'ComponentType', 'Test Point');
if ~isempty(tp)
    senseRef = tp.Refdes;
else
    res = findComponents(cnet, 'ComponentType', 'Resistor');
    senseRef = res.Refdes(1);  % use first resistor as sense fallback
end
setNetworkParameters(PDN, Source=src, Load=load, Sense=senseRef, ...
    PlatingThickness=0.002);
```

#### Multiphase Rails

For multiphase VRM designs, multiple inductors feed the same rail. Always use all inductors as Source, not just the first:

```matlab
inductors = findComponents(cnet, "ComponentType", "Inductor");
setNetworkParameters(PDN, Source=inductors.Refdes);  % handles multiphase
```

### setDCParameters -- Set Electrical Parameters

```matlab
setDCParameters(PDN, "NominalVoltage", 0.8, "LoadCurrent", 1);  % placeholder — ask user for actual value
```

### setDCRules -- Set DC Design Rules

```matlab
setDCRules(PDN, ...
    "MaxCurrentDensity", 0.5, ...
    "MaxVoltage", 0.816, ...
    "MinVoltage", 0.784, ...
    "MaxViaCurrent", 500);
```

**DC rules units (mixed — specific to this API):**

| Property | Units | Description |
|----------|-------|-------------|
| `PlatingThickness` | inches | Via barrel plating thickness (0.002 = 2 mil) |
| `NominalVoltage` | V | Nominal rail voltage |
| `LoadCurrent` | A | Expected load current per sink |
| `MaxCurrentDensity` | mA/mil² | Current density thermal limit |
| `MinVoltage` | V | Minimum allowable absolute voltage |
| `MaxVoltage` | V | Maximum allowable absolute voltage |
| `MaxViaCurrent` | mA | Max current through a single via |

**Voltage tolerance guidelines:**

| Rail Voltage | Tolerance | MinVoltage | MaxVoltage |
|---|---|---|---|
| < 1 V | 1–2% | P0V8: 0.8 × 0.98 = **0.784 V** | 0.8 × 1.02 = **0.816 V** |
| 1–3.3 V | 2–3% | P1V8: 1.8 × 0.975 = **1.755 V** | 1.8 × 1.025 = **1.845 V** |
| 3.3–5 V | 3–5% | P3V3: 3.3 × 0.97 = **3.201 V** | 3.3 × 1.03 = **3.399 V** |

## DC Analysis

### Voltage Distribution

```matlab
voltage(PDN);

% Show design rule violations
voltage(PDN, ShowViolation=true);
```

### Current Distribution

```matlab
current(PDN);

% Show current direction arrows
current(PDN, Direction='on');
```

### Inspecting PDN Configuration Before Analysis

Check the PDN model properties after setup to verify assignments:

```matlab
PDN.Source
PDN.Load
PDN.Sense
PDN.NominalVoltage
PDN.LoadCurrent
```

## Workflow: Single-Net PDN Analysis

Interactive workflow for analyzing one power net end-to-end:

```matlab
%% Step 1: Import the board
pcb = pcbFileRead(fullfile(boardDir, 'pcie5_native'));

%% Step 2: Identify power nets
netList = cadnetList(pcb);
powerPatterns = ["^P\d+V", "^VDD", "^VCC", "^AVDD", "^DVDD"];
isPower = false(height(netList), 1);
for p = powerPatterns
    isPower = isPower | ~cellfun(@isempty, regexpi(netList.CadnetName, p));
end
powerNets = sortrows(netList(isPower, :), 'NumPins', 'descend');
disp(powerNets);

%% Step 3: Create cadnet and inspect
cnet = cadnet(pcb, 'P0V8');
show(cnet);

%% Step 4: Discover components for topology assignment
allComps = findComponents(cnet);
inductors = findComponents(cnet, "ComponentType", "Inductor");
ics       = findComponents(cnet, "ComponentType", "IC");
resistors = findComponents(cnet, "ComponentType", "Resistor");

%% Step 5: Resolve voltage from net name
nomV = parseNetVoltage('P0V8');  % 0.8 V (see helper function above)

%% Step 6: Create and configure PDN
PDN = powerDistributionNetwork(cnet);

setNetworkParameters(PDN, ...
    Source=inductors.Refdes, ...
    Load=ics.Refdes, ...
    Sense=resistors.Refdes(1), ...
    PlatingThickness=0.002);

setDCParameters(PDN, "NominalVoltage", nomV, "LoadCurrent", 1);  % placeholder — ask user for actual value

tolerancePct = 0.02;  % 2% for <1V rails
setDCRules(PDN, ...
    "MaxCurrentDensity", 0.5, ...
    "MaxVoltage", nomV * (1 + tolerancePct), ...
    "MinVoltage", nomV * (1 - tolerancePct), ...
    "MaxViaCurrent", 500);

%% Step 7: Run analysis
voltage(PDN, ShowViolation=true);
current(PDN, Direction='on');
```

## Workflow: Multi-Net Batch Analysis

For batch analysis of all power rails on a board (loop with skip logic, per-rail spec tables), see [references/batch-analysis.md](references/batch-analysis.md).

## Common Patterns

### Component Refdes Usage

`findComponents` returns `Refdes` as a string -- use directly in `setNetworkParameters`. Use all matching components, not just the first:

```matlab
inductors = findComponents(cnet, "ComponentType", "Inductor");
setNetworkParameters(PDN, Source=inductors.Refdes);  % all inductors
```

### When to Use AutoAssignDefault

Use `AutoAssignDefault='True'` only when:
- No inductors found on the net (LDO rails, connector-fed rails)
- User explicitly requests automatic topology assignment
- Quick screening mode where accuracy is secondary

Always prefer explicit `findComponents`-based assignment.

### Z-Axis Visualization

Use `daspect` to see Z-axis detail in 3D views:

```matlab
ax = gca;
daspect(ax, [1, 1, 0.05]);
```

## Pitfalls

1. **`inferRailVoltage` returns `NaN` for unrecognized nets.** Guard with `isnan()` before using the result in calculations or display (e.g., `string(NaN)` produces `"NaN"`, not `missing`).

2. **`Sense` parameter is required in `setNetworkParameters`.** When no test point exists on the net, use a resistor as the sense component. Omitting `Sense` will cause errors during analysis.

3. **`AutoAssignDefault` is a fallback, not a first choice.** It may produce incorrect topology assignments on complex rails (LDO, connector-fed). Prefer explicit assignment via `findComponents` output.

4. **`LoadCurrent` cannot be inferred from board data — STOP and ask.** Unlike `NominalVoltage` (which can be parsed from net names), load current must come from IC datasheets or system power budgets. Before calling `setDCParameters`, ask the user for the actual load current and **STOP execution — do not proceed until the user responds.** Do NOT assume 1 A or any default without explicit user confirmation. Once the user responds that they don't have it or asks you to proceed, present these estimation options and let them choose:
   - **Per-pin heuristic:** 0.5 A × number of load pins (e.g., 130 pins → 65 A)
   - **TDP-based:** total power budget ÷ rail voltage (e.g., 40 W ÷ 0.8 V = 50 A)
   - **Fixed conservative:** 10 A per load IC (quick screening)
   - **1 A token:** minimal value to verify the workflow runs end-to-end

   Only after the user selects an option or provides a value, proceed with `setDCParameters`.

5. **`LoadCurrent` must be a vector, not a scalar total.** When multiple load ICs exist on a rail, `setDCParameters` requires one current value per load. For example, with loads U1 (4.8 A) and U9 (0.2 A): `setDCParameters(PDN, LoadCurrent=[4.8, 0.2])`. Passing a scalar (e.g., `LoadCurrent=5`) errors when the topology has more than one load.

6. **PDN units are mixed — not all SI.** `PlatingThickness` is in **inches** (not meters): `0.002` = 2 mil ≈ 1.4 oz copper. `MaxCurrentDensity` is **mA/mil²** (not A/mm²). `MaxViaCurrent` is **mA** (not A). `MinVoltage`/`MaxVoltage` are absolute **volts**. Using meters for plating (e.g., `35e-6`) or amps for via current (e.g., `1`) produces wildly incorrect results.

7. **Batch mode: skip rather than block.** When a rail is missing voltage, source, or load information, skip it and report which rails were skipped and why. Do not halt the entire batch for one incomplete rail.

8. **Large boards have 3000+ nets.** `cadnetList` returns all nets. Filter with regex on `CadnetName` to narrow to power/ground nets, then further filter by `NumPins` or specific patterns.

9. **`cnet.Voltage` is unreliable.** The `Voltage` property on the cadnet object is populated heuristically from the PCB file and often returns `'0.000'` even for valid power rails. Always parse the voltage from the net name using regex instead of relying on this property.

10. **No built-in `findPowerNets` or `inferRailVoltage`.** These do not exist as MATLAB functions. Use `cadnetList(pcb)` + `regexpi` filtering for net discovery, and the `parseNetVoltage` helper (defined in this skill) for voltage inference from net names.

11. **`.brd` files require extracta — STOP if unavailable.** If the user only has a `.brd` file and `extractaSetup()` returns `[]` or errors, STOP and inform the user: extracta (from a Cadence install) is required. Offer alternatives: (a) provide the path to `extracta.exe`, (b) export from Allegro as ODB++ or native CSV format, (c) use a colleague's Cadence install to convert. Do not attempt workarounds.

## Related Skills

- `matlab-read-pcb-layout` -- Importing PCB/package layouts for PDN analysis
- `matlab-manage-pcb-material` -- Substrate and conductor material setup
- `matlab-model-via` -- Via modeling for power delivery paths
- `matlab-analyze-em` -- EM analysis fundamentals

----

Copyright 2026 The MathWorks, Inc.

More from matlab/matlab-agentic-toolkit

SkillDescription
matlab-access-datafeed>
matlab-add-awgnRead BEFORE writing any code that adds Additive White Gaussian Noise (AWGN) to signals and converts between SNR, Eb/No, Es/No, and per-subcarrier SNR for communications simulations, using awgn(), convertSNR(), berawgn(). The default MATLAB patterns for AWGN (e.g., 'measured' option, manual SNR formulas) produce subtly incorrect results. This skill specifies the correct calling conventions, required function usage, and critical anti-patterns that must be avoided.
matlab-analyze-ams-waveformAnalyze AMS waveform data using Mixed-Signal Blockset utilities: phase noise measurement, clock jitter, anti-aliased resampling, timing measurements, lock time, INL/DNL, ADC/DAC calibration, HSpice import. Use when analyzing time-domain voltage from PLL/VCO/clock simulations, measuring phase noise from variable-step solver output, computing jitter, or resampling non-uniform data.
matlab-analyze-dataAnalyze data using MATLAB. Use when the task involves tables, timetables, time-series data, numeric arrays, sensor matrices, or gridded data — including but not limited to exploring, filtering, sorting, cleaning, transforming, aggregating, smoothing, padding, trimming, and answering questions about data. MATLAB provides extensive, easy-to-use built-in functions for these workflows with no additional products required.
matlab-analyze-dependenciesAnalyze the effective toolbox file set to produce a Dependency Manifest — classify all transitive dependencies as included, product, add-on, or external-unresolved, then present resolution options with tradeoffs. Use after matlab-define-toolbox-api when the spec is approved.
matlab-analyze-emS-parameters, insertion loss, fields, currents, mesh control, and solver selection for RF PCB performance validation. TRIGGER: user asks to compute S-parameters, analyze insertion/return loss, extract fields or currents, compare MoM vs FEM, or control mesh for any RF PCB component. Invoke BEFORE writing sparameters() or solver code — API is non-obvious. SKIP: designing or creating components (use the specific matlab-design-pcb-* skill), material/stackup setup only (use matlab-manage-pcb-material), optimization sweeps (use matlab-optimize-pcb-design), PDN/IR-drop analysis (use matlab-analyze-pcb-pdn).
matlab-analyze-installed-antennaAnalyze antennas installed on electrically large conducting platforms using MATLAB Antenna Toolbox. Loads platform geometry from STL/STEP/IGES, installs antenna elements, selects electromagnetic solvers (MoM-PO, FMM, MoM), and computes patterns, impedance, coupling, and efficiency. Use when the user wants to model an antenna on a vehicle, aircraft, ship, satellite, or other large structure.
matlab-analyze-rcsCalculate and visualize monostatic and bistatic radar cross section (RCS) using MATLAB Antenna Toolbox. Computes RCS of platforms, antennas, and arrays with PO, MoM, and FMM solvers, supporting HH/VV/HV/VH polarization, GPU acceleration, and near-field observation. Use when the user wants to compute, plot, or analyze radar cross section.
matlab-analyze-rf-propagationAnalyze RF propagation and plan wireless sites using MATLAB Antenna Toolbox. Creates transmitter/receiver sites, computes signal strength, coverage maps, SINR, line-of-sight, and ray tracing in geographic or indoor environments. Supports multiple propagation models (free-space, close-in, Longley-Rice, ray tracing, rain/gas/fog), custom terrain, building data, and directional antennas. Use when the user wants to compute coverage, signal strength, path loss, SINR, ray tracing, or plan a wireless network.
matlab-analyze-signal-cwt>