find-high-speed-nets
npx skills add https://github.com/drandyhaas/kicadroutingtools --skill find-high-speed-nets
Agent 安装分布
Skill 文档
Find High-Speed Nets
When this skill is invoked with a KiCad PCB file, perform a comprehensive analysis to identify which nets carry high-speed signals and recommend appropriate signal integrity measures.
Step 1: Load and Extract Components
from kicad_parser import parse_kicad_pcb
pcb = parse_kicad_pcb('path/to/file.kicad_pcb')
# Basic stats
print(f'Total nets: {len(pcb.nets)}')
print(f'Total footprints: {len(pcb.footprints)}')
Also run list_nets.py to get differential pairs and power nets (these inform the analysis):
python3 list_nets.py path/to/file.kicad_pcb --diff-pairs --power
Note: Differential pairs are handled separately by route_diff.py, which adds its own GND
return vias automatically. This analysis focuses on single-ended signal vias from route.py.
Step 2: Pre-Classify Nets by Name Patterns
Scan all net names (case-insensitive) to get an initial speed estimate before datasheet lookup:
speed_tiers = {
'ultra_high': { # >1 GHz
'patterns': ['DDR3', 'DDR4', 'DDR5', 'LPDDR', 'PCIE', 'SATA',
'USB3', 'SGMII', 'XGMII', 'TMDS', '10G'],
'typical_freq_mhz': 1600,
'typical_rise_ns': 0.3,
},
'high': { # 100 MHz - 1 GHz
'patterns': ['DDR', 'DQ', 'DQS', 'DQM', 'RGMII', 'RMII',
'QSPI', 'QIO', 'SDIO', 'LVDS', 'HDMI',
'USB', 'ETH', 'ULPI', 'EMMC'],
'typical_freq_mhz': 200,
'typical_rise_ns': 1.0,
},
'medium': { # 10 - 100 MHz
'patterns': ['SPI', 'SCK', 'SCLK', 'MOSI', 'MISO',
'CLK', 'MCLK', 'BCLK', 'JTAG', 'TCK',
'TDI', 'TDO', 'TMS', 'SWDIO', 'SWCLK',
'CAN', 'SDMMC'],
'typical_freq_mhz': 50,
'typical_rise_ns': 3.0,
},
'low': { # <10 MHz
'patterns': ['I2C', 'SCL', 'SDA', 'UART', 'TX', 'RX',
'GPIO', 'LED', 'BTN', 'SW_', 'ADC', 'DAC',
'PWM', 'RST', 'RESET', 'EN', 'ENABLE',
'IRQ', 'INT'],
'typical_freq_mhz': 1,
'typical_rise_ns': 10.0,
},
}
# Build initial classification
net_speed = {} # {net_name: (tier, interface_guess, freq_mhz)}
for net in pcb.nets.values():
if not net.name or net.name == '':
continue
name_upper = net.name.upper()
for tier, info in speed_tiers.items():
if any(pat in name_upper for pat in info['patterns']):
net_speed[net.name] = (tier, 'name_match', info['typical_freq_mhz'])
break
Report the initial classification to the user: how many nets in each tier, which patterns matched.
Step 3: Pre-Classify Components by Footprint and Value
Check footprint names and component values for high-speed indicators:
hs_component_keywords = {
'FPGA': ('ultra_high', 'Programmable logic - likely LVDS/DDR/SerDes'),
'CPLD': ('high', 'Programmable logic - check I/O speed'),
'DDR': ('ultra_high', 'DDR memory'),
'SDRAM': ('high', 'SDRAM - check generation (DDR2/3/4)'),
'LPDDR': ('ultra_high', 'Low-power DDR memory'),
'USB': ('high', 'USB interface - check version (1.1/2.0/3.x)'),
'ETH': ('high', 'Ethernet - check speed (10/100/1000)'),
'PHY': ('high', 'PHY transceiver - check interface type'),
'SERDES':('ultra_high', 'Serializer/deserializer'),
'XCVR': ('ultra_high', 'Transceiver - multi-GHz serial'),
'HDMI': ('ultra_high', 'HDMI - TMDS lanes'),
}
high_speed_components = [] # [(ref, footprint, tier, notes)]
for ref, fp in pcb.footprints.items():
name_upper = fp.footprint_name.upper()
for kw, (tier, notes) in hs_component_keywords.items():
if kw in name_upper:
high_speed_components.append((ref, fp.footprint_name, tier, notes))
break
# Also flag ICs with high pin count (>40 pins) as likely having fast interfaces
for ref, fp in pcb.footprints.items():
if ref.upper().startswith('U') and len(fp.pads) > 40:
if ref not in [c[0] for c in high_speed_components]:
high_speed_components.append((ref, fp.footprint_name, 'unknown',
f'{len(fp.pads)}-pin IC - needs datasheet lookup'))
Report components found and which need AI analysis.
Step 4: AI Datasheet Lookup
For each IC (U*), non-trivial connector, and any component flagged in Step 3, use WebSearch to find datasheet information about signal speeds.
4a. Search for Interface Speeds
WebSearch: "<part_value> <footprint_hint> datasheet maximum clock frequency"
Examples:
"MCF5213 ColdFire datasheet bus clock speed"– Find MCU bus frequency"XCR3256 CPLD datasheet I/O toggle rate"– Find CPLD max speed"KSZ9031 Ethernet PHY datasheet RGMII clock"– Find PHY interface speed"W25Q128 QSPI flash datasheet SPI clock frequency"– Find flash max SPI clock"FT2232H USB datasheet interface speed"– Find USB version and speed"IS42S16160 SDRAM datasheet CAS latency clock"– Find SDRAM clock speed"STM32F407 datasheet peripheral clock speeds"– Find MCU interface speeds
4b. Extract Speed Information
From each datasheet result, extract:
| Field | What to Look For |
|---|---|
| Interface type | SPI, I2C, UART, USB 2.0 HS, DDR3-1600, RGMII, etc. |
| Max clock/data rate | Bus clock in MHz/GHz, data rate in MT/s or Gbps |
| Output rise time | tr/tf in ns or ps (often in “Switching Characteristics” table) |
| I/O standards | LVCMOS, LVTTL, LVDS, HSTL, SSTL (for FPGAs) |
4c. Map to Specific Pins and Nets
For each interface found, identify which pins carry the fast signals:
# Map IC interface pins to nets
for ref, fp in pcb.footprints.items():
for pad in fp.pads:
if pad.pinfunction:
func_upper = pad.pinfunction.upper()
# Check if this pin is part of a high-speed interface
# e.g., pinfunction="SPI_CLK" on an MCU â that net is SPI speed
Record per-component findings:
- Component ref and value
- Each interface found: protocol, max frequency, rise time (if available)
- Which net names are associated with each interface
4d. Update Net Classifications
Upgrade net classifications based on datasheet findings. A datasheet-confirmed speed always overrides the name-pattern estimate from Step 2.
Step 5: Trace High-Speed Signals Through Series Passives
High-speed signals often pass through series components (termination resistors, AC coupling caps, ferrite beads). The nets on both sides carry the same speed signal.
# Build map of 2-pad series passives
series_passives = {} # {ref: (net_a, net_b)}
for ref, fp in pcb.footprints.items():
ref_upper = ref.upper()
is_passive = any(ref_upper.startswith(p) and (len(ref_upper) <= 1 or
ref_upper[len(p):len(p)+1].isdigit())
for p in ['R', 'C', 'L', 'FB'])
if is_passive and len(fp.pads) == 2:
net_a = fp.pads[0].net_name
net_b = fp.pads[1].net_name
if net_a and net_b and net_a != net_b:
series_passives[ref] = (net_a, net_b)
# BFS: propagate speed classification through series passives
# If net_a is classified high-speed, net_b inherits the same classification
from collections import deque
def propagate_speeds(net_speed, series_passives):
# Build adjacency: net â [connected nets via passives]
adjacency = {}
for ref, (net_a, net_b) in series_passives.items():
adjacency.setdefault(net_a, []).append(net_b)
adjacency.setdefault(net_b, []).append(net_a)
# BFS from each classified net
propagated = {}
for net_name, (tier, interface, freq) in list(net_speed.items()):
queue = deque([net_name])
visited = {net_name}
while queue:
current = queue.popleft()
for neighbor in adjacency.get(current, []):
if neighbor not in visited and neighbor not in net_speed:
propagated[neighbor] = (tier, f'{interface} via series passive', freq)
visited.add(neighbor)
queue.append(neighbor)
net_speed.update(propagated)
return propagated # return newly classified nets for reporting
Report which nets were added by propagation (e.g., “Net-R1-Pad2 classified as high-speed via series resistor R1 from SPI_CLK”).
Step 6: Generate Report
Per-Interface Groups
Group nets by interface and source/destination components:
## High-Speed Net Analysis for board.kicad_pcb
### Interface Groups
**SPI bus: U1 (STM32F407) <-> U3 (W25Q128)**
- /SPI_CLK: 50 MHz (datasheet-confirmed)
- /SPI_MOSI: 50 MHz (same bus)
- /SPI_MISO: 50 MHz (same bus)
- /SPI_CS: 50 MHz (same bus)
- Speed class: Medium
**DDR3 memory: U1 <-> U5 (MT41K256)**
- /DDR_DQ0..DQ15: 800 MHz (DDR3-1600)
- /DDR_DQS0, DQS1: 800 MHz
- /DDR_CLK: 800 MHz
- /DDR_A0..A14: 800 MHz
- Speed class: Ultra-high
Speed Summary Table
| Net Name | Interface | Component | Max Freq | Rise Time | Speed Class |
|----------|-----------|-----------|----------|-----------|-------------|
| /DDR_DQ0 | DDR3 | U1<->U5 | 800 MHz | ~0.3 ns | Ultra-high |
| /SPI_CLK | SPI | U1<->U3 | 50 MHz | ~3 ns | Medium |
| /I2C_SCL | I2C | U1<->U2 | 400 kHz | ~100 ns | Low |
GND Return Via Recommendation
Based on the highest speed class found on the board:
| Speed Class | Frequency | Recommended --gnd-via-distance |
Rationale |
|---|---|---|---|
| Ultra-high | >1 GHz | 2.0 mm | Return path critical; lambda/20 ~ 7 mm at 1 GHz in FR4 |
| High | 100 MHz – 1 GHz | 3.0 mm | Good return path, moderate density |
| Medium | 10 – 100 MHz | 5.0 mm | Return current less localized |
| Low | <10 MHz | Skip | Plane provides adequate return path |
| Minimum physical | any | 3 x (via_size + clearance) | Vias cannot physically fit closer |
For this board, the tightest interface is [interface] at [freq], so use:
--add-gnd-vias --gnd-via-distance [recommended_value]
Note: Differential pairs (detected by /plan-pcb-routing or list_nets.py --diff-pairs)
are routed with route_diff.py, which adds its own GND return vias automatically.
The --gnd-via-distance recommendation here applies to single-ended signal vias only.
Impedance Notes (if applicable)
If high-speed interfaces are detected, note relevant impedance targets:
| Interface | Typical Impedance | Notes |
|---|---|---|
| DDR3/4 | 40 ohm SE | SSTL, check memory controller spec |
| USB 2.0 HS | 90 ohm diff | Routed as diff pair |
| USB 3.x | 85 ohm diff | Routed as diff pair |
| Gigabit Ethernet | 100 ohm diff | Routed as diff pair |
| LVDS | 100 ohm diff | Routed as diff pair |
| PCIe | 85 ohm diff | Routed as diff pair |
| SPI/I2C/UART | 50 ohm SE (typical) | Usually not impedance-controlled |
Important Notes
- Datasheet results override name-pattern guesses – A net named “CLK” could be 1 MHz or 1 GHz; the datasheet determines the actual speed
- Check all ICs, not just the obvious ones – A “simple” MCU may have USB HS, SDIO, or QSPI peripherals running at hundreds of MHz
- Series passives propagate speed – The net on the other side of a termination resistor or AC coupling cap carries the same speed signal
- Use the tightest distance – If the board has both DDR3 (ultra-high) and I2C (low), the GND return via distance should be set for the DDR3 signals (2.0 mm)
- Diff pairs are separate –
route_diff.pyhandles GND return vias for differential pairs independently; this analysis is for single-ended vias fromroute.py - When in doubt, include GND return vias – They cost only board space; omitting them on a board that needs them causes signal integrity and EMI problems