Loading...
Loading...
Analyzes a KiCad PCB to identify high-speed nets by looking up component datasheets via AI. Classifies nets by speed tier (ultra-high/high/medium/low), estimates max frequencies and rise times per interface, and recommends GND return via distances for signal integrity.
npx skill4agent add drandyhaas/kicadroutingtools find-high-speed-netsfrom 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)}')list_nets.pypython3 list_nets.py path/to/file.kicad_pcb --diff-pairs --powerroute_diff.pyroute.pyspeed_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'])
breakhs_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'))WebSearch: "<part_value> <footprint_hint> datasheet maximum clock frequency""MCF5213 ColdFire datasheet bus clock speed""XCR3256 CPLD datasheet I/O toggle rate""KSZ9031 Ethernet PHY datasheet RGMII clock""W25Q128 QSPI flash datasheet SPI clock frequency""FT2232H USB datasheet interface speed""IS42S16160 SDRAM datasheet CAS latency clock""STM32F407 datasheet peripheral clock speeds"| 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) |
# 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# 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## 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| 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 || Speed Class | Frequency | Recommended | 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 |
--add-gnd-vias --gnd-via-distance [recommended_value]/plan-pcb-routinglist_nets.py --diff-pairsroute_diff.py--gnd-via-distance| 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 |
route_diff.pyroute.py