Back to catalog

kicad-schematic-synthesizer

Skill from synqing/K1.hardware

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

# KiCad Schematic Synthesizer (SKiDL + ERC)

## Purpose
Converts a design spec into a **complete, ERC-checked schematic netlist** using SKiDL (programmatic schematic language). Ensures connectivity is code-driven, version-controlled, and deterministic.

## When Auto-Activate
**Keywords (trigger this skill):**
- `schematic`, `netlist`, `SKiDL`, `generate schematic`, `ERC`
- `circuit synthesis`, `connectivity`, `power tree`, `signal hierarchy`
- `symbol assignment`, `pin assignment`, `hierarchical schematic`

## Core Workflow

### 1. Read Design Spec
Load `hardware/k1-lightwave/design-spec.yaml`:
- Extract component list (MPNs, quantities, purposes)
- Extract electrical constraints (power rails, signal classes, diff pairs)
- Extract pin assignments (connectors, IO mapping)

### 2. Generate SKiDL Schematic
Create `hardware/k1-lightwave/kicad/k1_schematic.py` (or equiv):

```python
# k1_schematic.py — PCB netlist generator
from skidl import *

set_default_tool(KICAD)

# Configuration (from design-spec.yaml)
SPEC = load_yaml("../design-spec.yaml")

# Power tree (first priority: clean power distribution)
def power_tree():
    """Main power supply and regulators"""
    with Group("Power Distribution"):
        # Input connector (5V barrel jack / USB-C)
        J_POWER = Connector(
            name="J_POWER",
            part="USB_C_Receptacle_USB3.1_16P",
            description="5V input, 2A budget"
        )

        # Bulk decoupling (low-ESR ceramic)
        C_BULK1 = C(value="100µF", voltage="10V", description="Bulk cap near inlet")
        C_BULK2 = C(value="100µF", voltage="10V", description="Second bulk cap")
        Net("+5V") += [J_POWER[1], C_BULK1[1], C_BULK2[1]]
        Net("GND") += [J_POWER[5], C_BULK1[2], C_BULK2[2]]

        # 3.3V LDO (for logic and MCUs)
        U_VREG = IC(
            part="TPS54302",  # or AMS1117 (lower cost, higher dropout)
            pin_assignments={
                "IN": "+5V",
                "EN": "+5V",
                "FB": "VREF",
                "OUT": "+3V3",
                "GND": "GND"
            }
        )

        # Feedback divider for LDO
        R_FB_TOP = R(value="100k", tolerance="1%")
        R_FB_BOT = R(value="30k", tolerance="1%")
        Net("VREF") += [R_FB_TOP[1], R_FB_BOT[1], U_VREG.FB]

        # Output filter (low-ESR ceramic + electrolytic)
        C_3V3_BULK = C(value="47µF", voltage="10V")
        C_3V3_CERAMIC = C(value="100nF", voltage="10V")
        Net("+3V3") += [U_VREG.OUT, C_3V3_BULK[1], C_3V3_CERAMIC[1]]

# MCU cores (2× ESP32-S3)
def mcu_section():
    """MCU block: ESP32-S3 ×2 (audio + LED orchestration)"""
    with Group("MCU — Audio Core"):
        U_MCU_AUDIO = IC(
            part="ESP32-S3-WROOM-1",
            description="MCU: I2S audio capture"
        )
        decap_by_pin(U_MCU_AUDIO, "+3V3", "GND", [100, 10, 10], "nF")  # Auto-place caps

        # Crystal (external clock if needed; ESP32-S3 has internal)
        # (optional; skip for now if using internal clock)

        # Strapping pins (pulled to rail or GND for boot mode)
        # GPIO0=high for normal boot, GPIO45=high for SPI mode, etc.

    with Group("MCU — LED Core"):
        U_MCU_LED = IC(
            part="ESP32-S3-WROOM-1",
            description="MCU: WS2812B LED orchestration"
        )
        decap_by_pin(U_MCU_LED, "+3V3", "GND", [100, 10, 10], "nF")

# Audio input stage
def audio_section():
    """Audio capture: digital microphone (I2S) + clock tree"""
    with Group("Audio Input"):
        # Digital MEMS mic (I2S out)
        U_MIC = IC(
            part="SPH0645",
            description="MEMS digital microphone"
        )

        # I2S clock generator (if needed; ESP32-S3 can generate)
        # Or use MCU-generated clock

        # I2S routing to MCU_AUDIO
        # I2S_BCLK, I2S_LRCLK, I2S_DOUT → GPIO pins on MCU_AUDIO

# LED output stage
def led_section():
    """LED output: level shifter + connector"""
    with Group("LED Output"):
        # 3.3V → 5V level shifter (for WS2812B DATA line)
        U_LVSHIFT = IC(
            part="SN74AHCT125",  # 4-ch buffer, 3.3V input → 5V output
            description="Level shifter: 3.3V logic → 5V WS2812B"
        )

        # Decoupling for shifter
        decap_by_pin(U_LVSHIFT, "+5V", "GND", [100], "nF")

        # WS2812B connector (JST-XH 3-pin: GND, 5V, DATA)
        J_LED = Connector(
            name="J_LED",
            part="JST_XH_3pin",
            description="WS2812B output (GND, 5V, DATA)"
        )

        Net("GND") += [J_LED[1], U_LVSHIFT.GND]
        Net("+5V") += [J_LED[2], U_LVSHIFT.VCC]
        Net("LED_DATA_5V") += [J_LED[3], U_LVSHIFT.output]

# Top-level assembly
def generate_schematic():
    """Assemble all sections"""
    reset_connection_stack()

    # Power first (voltage stable before signal)
    power_tree()

    # Then MCUs + clocking
    mcu_section()

    # Then signal paths (audio, LED)
    audio_section()
    led_section()

    # Generate KiCad schematic file
    generate_netlist(file="k1_schematic.net")
    generate_kicad_sch_file(file="k1_lightwave.kicad_sch")

if __name__ == "__main__":
    generate_schematic()
    print("✅ Schematic generated: k1_lightwave.kicad_sch")
```

### 3. Run ERC (Electrical Rules Check)
```bash
kicad-cli sch erc k1_lightwave.kicad_sch --output json > erc-report.json
```

### 4. Parse ERC & Auto-Fix
Read `erc-report.json` and:
- **Power pin errors** → Add missing power connections or ground planes
- **Floating nets** → Connect unconnected signals or mark NC (no-connect)
- **Unassigned footprints** → Warn (footprint step is next)
- **High-voltage/current errors** → Suggest wire gauge or trace width

**Auto-fixes are conservative:** Only fix obvious mistakes; flag ambiguous issues for human review.

### 5. Iterate Until ERC=0
Loop steps 2–4 until no ERC violations:
```
ERC pass 1: 12 violations → Fix 10 auto → Manual review 2
ERC pass 2: 2 violations → Fix 1 → Manual review 1
ERC pass 3: 0 violations ✅
```

### 6. Commit & Document
```bash
git add hardware/k1-lightwave/kicad/k1_schematic.py
git add hardware/k1-lightwave/kicad/k1_lightwave.kicad_sch
git commit -m "Schematic synthesis: dual ESP32-S3, audio I2S, LED level shifter (ERC=0)"
```

---

## Tool Calls

**MCP Tools:**
- `sch_erc()` (kicad-cli) — Run headless ERC
- `rag_query()` — Fetch design patterns (power tree, I2S clock, level shifter best practices)
- `parts_search()` (Nexar) — Validate MPN footprints + alternatives

**Python Libraries:**
- SKiDL (https://skidl.readthedocs.io/)
- json/yaml (parse ERC report + spec)

---

## Outputs

1. **k1_schematic.py** — Versioned, code-driven source of truth for connectivity
2. **k1_lightwave.kicad_sch** — KiCad schematic file (auto-generated, human-readable)
3. **erc-report.json** — Structured ERC violations (empty on success)
4. **schematic-summary.md** — Human-readable audit (power tree, signal paths, pin count)

---

## Example Output

```
✅ Schematic synthesized:
  - Components: 2× ESP32-S3, 1× SPH0645, 1× SN74AHCT125, ~20 passive parts
  - Power tree: 5V → 3.3V LDO (TPS54302) w/ bulk caps + feedthrough
  - Signal paths: I2S (audio), WS2812B (LEDs), USB-C (power + debug)
  - Net count: 47
  - ERC violations: 0 ✅
  - Unassigned footprints: 0 ✅

✏️ Committed: kicad/k1_schematic.py + k1_lightwave.kicad_sch

→ Ready for Footprint Mapping & Part Binding (next step)
```

---

## Design Patterns (Built-In)

- **Power tree**: Input → bulk caps → regulator → bypass caps → load
- **I2S clock tree**: MCU generates BCLK/LRCLK → microphone consumes
- **Level shifter**: Always add 100nF bypass to supply pin
- **Decoupling**: 1× 100µF + 10µF + 10nF per IC power pin (ceramic preferred, low ESR)

---

## Integration with Downstream Agents

- **Part Picker** reads `k1_lightwave.kicad_sch` to extract symbols → maps footprints
- **PCB Synthesizer** reads netlist to generate board connectivity
- **Verifier** uses net list to validate DRC + manufacturability

---

## Notes

- SKiDL scripts are **deterministic**: same inputs → same schematic (ideal for CI/CD)
- ERC checks catch **electrical mistakes early** (wrong voltage, unconnected power)
- Auto-fixes are **conservative**: human always reviews before committing
- Schematic is **the source of truth** (not the KiCad GUI file)