Back to Embedded Systems Hardware Engineering Series

Part 6: Simulation & Verification

April 17, 2026 Wasil Zafar 45 min read

Verify your designs before committing to copper — master SPICE circuit simulation with LTspice and ngspice, signal integrity fundamentals, power delivery network analysis, and pre-layout validation techniques.

Table of Contents

  1. Why Simulate?
  2. SPICE Simulation
  3. Signal Integrity
  4. Power Integrity
  5. Exercises
  6. Simulation Report Tool
  7. Conclusion & Next Steps

Why Simulate Before You Fabricate?

Analogy Simulation is like a flight simulator for hardware engineers. Pilots don’t learn to fly by crashing real planes — they crash hundreds of times in a simulator first, learning what happens when you stall, lose an engine, or fly into a thunderstorm. SPICE simulation lets you “crash” your circuit design for free: overshoot the output of your voltage regulator, oscillate your feedback loop, brown out your MCU under load — all without burning a single component. The flight simulator doesn’t replace real flight hours, and SPICE doesn’t replace physical prototyping, but both save you from catastrophic (and expensive) failures.

A Brief History of Circuit Simulation

1971 Larry Nagel and Donald Pederson at UC Berkeley created SPICE (Simulation Program with Integrated Circuit Emphasis) as a graduate research project. It solved Kirchhoff’s equations using modified nodal analysis — the same algorithm every SPICE simulator uses today.
1975 SPICE2 was released into the public domain by Berkeley, making it the first universally available circuit simulator. Nearly every commercial SPICE tool (PSpice, HSpice, LTspice) descends from this codebase.
1998 Mike Engelhardt at Linear Technology released LTspice (then SwitchCAD), a free SPICE simulator with integrated schematic capture. It became the de facto standard for power supply simulation and remains free under Analog Devices.
2023 Qorvo released QSPICE, a modern SPICE simulator with C/C++ model support and a redesigned GUI, challenging LTspice’s 25-year dominance in the free-tool space.

A PCB re-spin costs $200–$2,000+ in fabrication, assembly, and engineering time. A simulation costs you an afternoon. SPICE simulation catches circuit bugs — wrong resistor values, unstable feedback loops, insufficient decoupling — before you commit to physical copper. Signal and power integrity analysis ensures your high-speed signals arrive clean and your power rails stay stable under load.

Industry reality: Professional hardware teams simulate every power supply, every feedback loop, and every high-speed interface before tapeout. The cost of simulation is effectively zero compared to a single board re-spin.

Simulation Tool Landscape

ToolTypeCostBest For
LTspiceSPICE (Analog Devices)FreePower supply, analog circuits
ngspiceSPICE (open source)FreeKiCad integration, scripting
QSPICESPICE (Qorvo)FreeModern UI, C/C++ models
Altium SPICEIntegrated SPICEIncludedIn-schematic simulation
HyperLynxSignal/Power integrity$$$$High-speed PCB verification
Ansys RedHawkPower integrity$$$$IC/package-level PDN analysis
Ansys HFSSEM simulation$$$$Antenna, connector, high-freq design
Cadence SpectreSPICE (Cadence)$$$$Custom IC, analog/mixed-signal
Synopsys PrimeTimeStatic timing analysis$$$$IC timing signoff
Siemens CalibreDRC/LVS/signoff$$$$IC physical verification (industry standard)
Python + SciPyNumerical analysisFreeCustom models, automation

SPICE Circuit Simulation

SPICE Fundamentals

SPICE (Simulation Program with Integrated Circuit Emphasis) solves Kirchhoff’s equations numerically for arbitrary circuits. You define a netlist of components and connections, specify an analysis type (DC, AC, transient), and SPICE computes voltages and currents at every node over time or frequency.

SPICE Simulation Workflow
flowchart LR
    A[Schematic / Netlist] --> B[Component Models]
    B --> C[Analysis Type]
    C --> D[SPICE Solver]
    D --> E[Waveform Viewer]
    E --> F[Design Validation]
                            
# Example ngspice netlist: Voltage divider
# Save as voltage_divider.spice

cat <<'EOF' > voltage_divider.spice
* Voltage Divider Simulation
V1 in 0 DC 3.3
R1 in out 10k
R2 out 0 10k

.op
.end
EOF

# Run ngspice (if installed)
# ngspice voltage_divider.spice
# Expected output: V(out) = 1.65V (half of 3.3V)
echo "Expected: V(out) = 3.3 × 10k/(10k+10k) = 1.65V"
Output
Expected: V(out) = 3.3 × 10k/(10k+10k) = 1.65V

ngspice output (if run):
  Node voltages:
    V(in)  = 3.300000e+00
    V(out) = 1.650000e+00
  Branch currents:
    I(V1) = -1.650000e-04  (165µA through divider)

Transient Analysis

Transient analysis simulates circuit behaviour over time — essential for power supply startup, digital signal timing, and filter response. It computes node voltages at discrete time steps.

import numpy as np
import matplotlib
matplotlib.use('Agg')  # Non-interactive backend
import matplotlib.pyplot as plt

# Simulate RC circuit transient response
# V_out(t) = V_in × (1 - e^(-t/RC))
R = 10e3     # 10kΩ
C = 100e-9   # 100nF
tau = R * C  # Time constant

t = np.linspace(0, 5 * tau, 1000)
v_in = 3.3
v_out = v_in * (1 - np.exp(-t / tau))

print(f"R = {R/1e3:.0f}kΩ, C = {C*1e9:.0f}nF")
print(f"Time constant τ = RC = {tau*1e6:.0f}µs")
print(f"Rise to 63.2%: {tau*1e6:.0f}µs → V = {v_in * 0.632:.2f}V")
print(f"Rise to 95%:   {3*tau*1e6:.0f}µs → V = {v_in * 0.95:.2f}V")
print(f"Rise to 99%:   {5*tau*1e6:.0f}µs → V = {v_in * 0.99:.2f}V")

# Key points for hardware design
print(f"\nHardware implication:")
print(f"A 10kΩ pull-up with 100nF decoupling takes {5*tau*1e6:.0f}µs to settle")
print(f"For a 1MHz I2C bus, this is too slow (1µs bit time)")
Output
R = 10kΩ, C = 100nF
Time constant τ = RC = 1000µs
Rise to 63.2%: 1000µs → V = 2.09V
Rise to 95%:   3000µs → V = 3.14V
Rise to 99%:   5000µs → V = 3.27V

Hardware implication:
A 10kΩ pull-up with 100nF decoupling takes 5000µs to settle
For a 1MHz I2C bus, this is too slow (1µs bit time)

AC Sweep & Bode Plots

AC sweep analysis measures how a circuit responds across a range of frequencies — producing a Bode plot (gain and phase vs frequency). This is critical for verifying filter designs and feedback loop stability.

import numpy as np

# Low-pass RC filter frequency response
# H(f) = 1 / (1 + j × 2π × f × R × C)
R = 10e3    # 10kΩ
C = 100e-9  # 100nF
f_cutoff = 1 / (2 * np.pi * R * C)

frequencies = np.logspace(1, 7, 100)  # 10 Hz to 10 MHz
omega = 2 * np.pi * frequencies
H = 1 / (1 + 1j * omega * R * C)

gain_db = 20 * np.log10(np.abs(H))
phase_deg = np.degrees(np.angle(H))

print(f"Low-pass RC filter: R={R/1e3:.0f}kΩ, C={C*1e9:.0f}nF")
print(f"Cutoff frequency (-3dB): {f_cutoff:.0f} Hz ({f_cutoff/1e3:.2f} kHz)")
print(f"\nFrequency Response:")
print(f"{'Frequency':>12} | {'Gain (dB)':>10} | {'Phase (°)':>10}")
print("-" * 40)

check_freqs = [100, 1000, f_cutoff, 10000, 100000, 1000000]
for f in check_freqs:
    h = 1 / (1 + 1j * 2 * np.pi * f * R * C)
    g = 20 * np.log10(abs(h))
    p = np.degrees(np.angle(h))
    label = " ← fc" if abs(f - f_cutoff) < 1 else ""
    print(f"{f:>10.0f} Hz | {g:>8.1f} dB | {p:>8.1f}°{label}")
Output
Low-pass RC filter: R=10kΩ, C=100nF
Cutoff frequency (-3dB): 159 Hz (0.16 kHz)

Frequency Response:
   Frequency |  Gain (dB) |  Phase (°)
----------------------------------------
       100 Hz |     -0.8 dB |    -32.1°
      1000 Hz |    -16.2 dB |    -80.9°
       159 Hz |     -3.0 dB |    -45.0° ← fc
     10000 Hz |    -36.1 dB |    -89.1°
    100000 Hz |    -56.0 dB |    -89.9°
   1000000 Hz |    -76.0 dB |    -90.0°

DC Operating Point Analysis

DC operating point analysis computes the steady-state DC voltages and currents in your circuit. Use it to verify bias points for amplifiers, voltage divider outputs, and power rail levels.

import numpy as np

# Verify a voltage reference circuit
# Using resistive divider with buffer
v_supply = 5.0
r1 = 10e3   # Top resistor
r2 = 6.8e3  # Bottom resistor

# Thevenin equivalent
v_th = v_supply * r2 / (r1 + r2)
r_th = (r1 * r2) / (r1 + r2)

print("DC Operating Point: Voltage Reference Circuit")
print("=" * 45)
print(f"V_supply: {v_supply}V")
print(f"R1: {r1/1e3:.1f}kΩ, R2: {r2/1e3:.1f}kΩ")
print(f"V_out (divider): {v_th:.3f}V")
print(f"R_thevenin: {r_th/1e3:.2f}kΩ")

# Current through divider
i_divider = v_supply / (r1 + r2)
p_total = v_supply * i_divider

print(f"\nDivider current: {i_divider*1e3:.2f}mA")
print(f"Power dissipated: {p_total*1e3:.2f}mW")
print(f"R1 dissipation: {i_divider**2 * r1 * 1e3:.2f}mW")
print(f"R2 dissipation: {i_divider**2 * r2 * 1e3:.2f}mW")
Output
DC Operating Point: Voltage Reference Circuit
=============================================
V_supply: 5.0V
R1: 10.0kΩ, R2: 6.8kΩ
V_out (divider): 2.024V
R_thevenin: 4.05kΩ

Divider current: 0.30mA
Power dissipated: 1.49mW
R1 dissipation: 0.89mW
R2 dissipation: 0.60mW
Output
DC Operating Point: Voltage Reference Circuit
=============================================
V_supply: 5.0V
R1: 10.0kΩ, R2: 6.8kΩ
V_out (divider): 2.024V
R_thevenin: 4.05kΩ

Divider current: 0.30mA
Power dissipated: 1.49mW
R1 dissipation: 0.89mW
R2 dissipation: 0.60mW

Signal Integrity

Reflections & Termination

When a signal reaches the end of a transmission line, energy reflects back toward the source if the line impedance doesn’t match the load. These reflections cause ringing, overshoot, and false triggering — the bane of high-speed digital design.

Signal Reflection at Impedance Mismatch
flowchart LR
    DRV["Driver Z_out=25Ω"] -->|"Trace Z0=50Ω"| LOAD["Load Z_L=∞ (open)"]
    LOAD -->|"Reflected wave"| DRV
                            
import numpy as np

# Reflection coefficient calculator
# Γ = (Z_L - Z_0) / (Z_L + Z_0)
z0 = 50  # Characteristic impedance of trace

loads = [
    ("Open circuit (no termination)", 1e9),
    ("Short circuit", 0.001),
    ("50Ω matched termination", 50),
    ("100Ω (2× impedance)", 100),
    ("33Ω series termination", 33),
    ("Typical CMOS input (~10MΩ)", 10e6),
]

print("Reflection Coefficient Analysis")
print(f"Trace impedance Z0 = {z0}Ω")
print("=" * 55)
print(f"{'Load':>35} | {'Γ':>8} | {'Reflected %':>12}")
print("-" * 55)

for name, z_l in loads:
    gamma = (z_l - z0) / (z_l + z0)
    pct = abs(gamma) * 100
    print(f"{name:>35} | {gamma:>+7.3f} | {pct:>10.1f}%")

print("\nKey insight: CMOS inputs look like open circuits!")
print("→ Always terminate high-speed lines (>50MHz)")
Output
Reflection Coefficient Analysis
Trace impedance Z0 = 50Ω
=======================================================
                               Load |        Γ |  Reflected %
-------------------------------------------------------
       Open circuit (no termination) |  +1.000  |      100.0%
                      Short circuit  |  -1.000  |      100.0%
            50Ω matched termination  |  +0.000  |        0.0%
               100Ω (2× impedance)   |  +0.333  |       33.3%
             33Ω series termination   |  -0.205  |       20.5%
       Typical CMOS input (~10MΩ)    |  +1.000  |      100.0%

Key insight: CMOS inputs look like open circuits!
→ Always terminate high-speed lines (>50MHz)

Rise Time & Bandwidth

A signal becomes a transmission line problem when the trace length is comparable to the signal’s wavelength. The rule of thumb: if trace length > λ/10, you need controlled impedance.

import numpy as np

# When does a trace become a transmission line?
# Critical length = rise_time × propagation_speed / 10

# FR4 propagation speed ≈ 0.5 × speed of light
c = 3e8          # Speed of light (m/s)
v_prop = 0.5 * c # Propagation in FR4 (m/s)

print("Critical Trace Length Calculator")
print("=" * 50)
print(f"{'Rise Time':>12} | {'BW (0.35/tr)':>12} | {'Critical Length':>15}")
print("-" * 50)

rise_times = [10e-9, 5e-9, 2e-9, 1e-9, 0.5e-9, 0.2e-9]
for tr in rise_times:
    bw = 0.35 / tr
    critical_length = tr * v_prop / 10
    tr_str = f"{tr*1e9:.1f}ns" if tr >= 1e-9 else f"{tr*1e12:.0f}ps"
    bw_str = f"{bw/1e6:.0f}MHz" if bw < 1e9 else f"{bw/1e9:.1f}GHz"
    cl_str = f"{critical_length*100:.1f}cm" if critical_length > 0.01 else f"{critical_length*1000:.1f}mm"
    print(f"{tr_str:>12} | {bw_str:>12} | {cl_str:>15}")

print("\nExample: STM32 GPIO at 50MHz (tr≈5ns)")
print("Critical length = 7.5cm → anything longer needs Z-control")
Output
Critical Trace Length Calculator
==================================================
  Rise Time | BW (0.35/tr) | Critical Length
--------------------------------------------------
      10.0ns |        35MHz |          15.0cm
       5.0ns |        70MHz |           7.5cm
       2.0ns |       175MHz |           3.0cm
       1.0ns |       350MHz |           1.5cm
       500ps |       700MHz |           0.8cm
       200ps |      1.8GHz |           3.0mm

Example: STM32 GPIO at 50MHz (tr≈5ns)
Critical length = 7.5cm → anything longer needs Z-control

Eye Diagrams

An eye diagram overlays many bit transitions on top of each other, revealing signal quality at a glance. A wide-open “eye” means clean signalling; a closed eye means excessive jitter, noise, or inter-symbol interference.

Eye diagram metrics: (1) Eye height = voltage margin between 0 and 1 (larger is better). (2) Eye width = timing margin for sampling (wider is better). (3) Jitter = horizontal variation at crossing point (smaller is better). (4) Overshoot/undershoot = excursions beyond rail voltages.

Power Integrity

Power Delivery Network (PDN) Impedance

The Power Delivery Network is the system of voltage regulators, copper planes, vias, and decoupling capacitors that deliver clean power to every IC. The goal is to keep PDN impedance below a target value across the entire frequency range.

import numpy as np

# PDN target impedance calculator
# Z_target = ΔV_allowed / I_transient
# ΔV = ripple tolerance (typically 5% of VDD)
# I_transient = peak current step

v_dd = 3.3        # Supply voltage
ripple_pct = 0.05  # 5% ripple tolerance
i_transient = 0.5  # 500mA current step (MCU wakeup)

delta_v = v_dd * ripple_pct
z_target = delta_v / i_transient

print("PDN Target Impedance Calculator")
print("=" * 40)
print(f"VDD: {v_dd}V")
print(f"Ripple tolerance: {ripple_pct*100:.0f}% = {delta_v*1e3:.0f}mV")
print(f"Transient current: {i_transient*1e3:.0f}mA")
print(f"Target impedance: {z_target:.3f}Ω = {z_target*1e3:.0f}mΩ")

print(f"\nThis means the PDN impedance must be < {z_target*1e3:.0f}mΩ")
print(f"from DC to the MCU's clock frequency ({48}MHz)")

# What provides low impedance at each frequency?
print(f"\n--- Who handles each frequency range? ---")
bands = [
    ("DC - 1kHz", "Voltage Regulator (feedback loop)"),
    ("1kHz - 1MHz", "Bulk capacitors (10µF - 100µF)"),
    ("1MHz - 100MHz", "Decoupling caps (100nF MLCC)"),
    ("100MHz - 1GHz", "Small caps (100pF - 1nF) + PCB planes"),
]
for band, source in bands:
    print(f"  {band}: {source}")
Output
PDN Target Impedance Calculator
========================================
VDD: 3.3V
Ripple tolerance: 5% = 165mV
Transient current: 500mA
Target impedance: 0.330Ω = 330mΩ

This means the PDN impedance must be < 330mΩ
from DC to the MCU's clock frequency (48MHz)

--- Who handles each frequency range? ---
  DC - 1kHz: Voltage Regulator (feedback loop)
  1kHz - 1MHz: Bulk capacitors (10µF - 100µF)
  1MHz - 100MHz: Decoupling caps (100nF MLCC)
  100MHz - 1GHz: Small caps (100pF - 1nF) + PCB planes

Decoupling Capacitor Strategy Simulation

import numpy as np

# Impedance of parallel capacitors
# Z_cap = 1/(2πfC) with ESR and ESL
# Z = ESR + j(2πf×ESL - 1/(2πf×C))

caps = [
    {"label": "100µF bulk", "C": 100e-6, "ESR": 0.05, "ESL": 5e-9},
    {"label": "10µF MLCC",  "C": 10e-6,  "ESR": 0.01, "ESL": 1e-9},
    {"label": "100nF MLCC", "C": 100e-9, "ESR": 0.01, "ESL": 0.5e-9},
    {"label": "100pF MLCC", "C": 100e-12,"ESR": 0.05, "ESL": 0.3e-9},
]

freqs = [1e3, 10e3, 100e3, 1e6, 10e6, 100e6]

print("Capacitor Impedance vs Frequency (Ω)")
print("=" * 70)
header = f"{'Freq':>8} |"
for cap in caps:
    header += f" {cap['label']:>12} |"
print(header)
print("-" * 70)

for f in freqs:
    row = f"{f/1e3:>5.0f}kHz |" if f < 1e6 else f"{f/1e6:>5.0f}MHz |"
    for cap in caps:
        omega = 2 * np.pi * f
        z_c = 1 / (omega * cap['C'])
        z_l = omega * cap['ESL']
        z_total = np.sqrt(cap['ESR']**2 + (z_l - z_c)**2)
        row += f" {z_total:>10.4f}Ω |"
    print(row)

print("\nStrategy: Use ALL four values in parallel")
print("Each cap dominates a different frequency band")
Output
Capacitor Impedance vs Frequency (Ω)
======================================================================
    Freq |   100µF bulk |    10µF MLCC |   100nF MLCC |   100pF MLCC |
----------------------------------------------------------------------
    1kHz |     1.5915Ω  |    15.9155Ω  |  1591.5494Ω  |**************|
   10kHz |     0.1592Ω  |     1.5916Ω  |   159.1549Ω  |**************|
  100kHz |     0.0509Ω  |     0.1592Ω  |    15.9155Ω  |**************|
    1MHz |     0.0500Ω  |     0.0159Ω  |     1.5916Ω  |  1591.5494Ω  |
   10MHz |     0.0506Ω  |     0.0100Ω  |     0.1276Ω  |   159.1534Ω  |
  100MHz |     0.3092Ω  |     0.0528Ω  |     0.0298Ω  |    15.8657Ω  |

Strategy: Use ALL four values in parallel
Each cap dominates a different frequency band
Case Study
Ariane 5 Flight 501 — When Simulation Didn’t Match Reality (1996)

On June 4, 1996, the European Space Agency’s Ariane 5 rocket self-destructed 37 seconds after launch. The cause: a 64-bit floating-point value (horizontal velocity) was converted to a 16-bit signed integer, causing an overflow. The software was inherited from Ariane 4 and had been validated through simulation — but only for Ariane 4’s flight profile.

The simulation failure: The inertial reference system (SRI) software worked perfectly in simulation because the test cases used Ariane 4 trajectory data, where horizontal velocity never exceeded the 16-bit integer range (±32,767). Ariane 5’s more powerful boosters produced higher horizontal acceleration early in flight, pushing the value past 32,767 just 37 seconds in. The simulation validated the wrong operating envelope.

Engineering lesson: Simulation is only as good as your test vectors. Always simulate worst-case conditions, not just nominal operation. In embedded hardware, this means simulating maximum load transients, minimum input voltage, maximum temperature, and component tolerance extremes — not just the typical datasheet values. A $370 million payload was destroyed because nobody asked “what if the number is bigger than expected?”

$370M Loss Integer Overflow Wrong Test Vectors Worst-Case Analysis
Case Study
Xbox 360 Red Ring of Death — Thermal Simulation Underestimated Solder Fatigue (2005–2008)

Microsoft shipped the Xbox 360 in November 2005 with a known but underestimated thermal issue. The GPU (ATI Xenos) generated more heat than the cooling solution could dissipate during sustained gaming. Over thousands of thermal cycles, the lead-free BGA solder joints cracked, disconnecting the GPU from the motherboard — indicated by three red LEDs, the infamous “Red Ring of Death.”

The simulation gap: Microsoft’s thermal simulation predicted the GPU junction temperature under steady-state conditions but underestimated the thermal cycling stress on BGA solder joints. The simulation modelled heat flow through the heatsink and PCB copper but didn’t account for the coefficient of thermal expansion (CTE) mismatch between the silicon die (2.6 ppm/°C) and the FR4 PCB (14-17 ppm/°C) over 10,000+ power cycles. Each heat-cool cycle flexed the package by microns, propagating cracks through the solder balls.

Engineering lesson: Thermal simulation must include cyclic fatigue analysis, not just steady-state temperature. Use Coffin-Manson solder fatigue models in your simulation workflow. Microsoft’s $1.15 billion warranty extension could have been avoided with proper thermo-mechanical simulation during the design phase. Always simulate CTE mismatch and solder joint reliability for BGA packages.

$1.15B Warranty Thermal Cycling BGA Solder Fatigue CTE Mismatch

Exercises

Exercise 1: RC Filter Design & Verification

You need a low-pass filter on an ADC input to remove high-frequency noise from a temperature sensor signal. The sensor outputs 0–3.3V analog with useful information up to 100 Hz. The ADC samples at 1 kHz.

  1. Calculate R and C values for a single-pole RC low-pass filter with a -3dB cutoff at 100 Hz. Choose standard component values (E96 series for resistors, E12 for capacitors).
  2. Using the AC sweep code from this article, compute the attenuation at the ADC Nyquist frequency (500 Hz). Is this sufficient to prevent aliasing?
  3. What is the time constant of your filter? How long does the output take to settle to 99% of a step input?
  4. If the ADC has 100pF input capacitance, how does this affect your filter’s cutoff frequency? Recalculate.

Hint: fc = 1/(2πRC) = 100Hz → RC = 1.59ms. Try R = 15kΩ, C = 100nF → fc = 106 Hz. At 500Hz: attenuation = -20log10(√(1+(500/106)²)) ≈ -13.5 dB. Time constant = 1.5ms, 99% settling = 7.5ms. With 100pF ADC input: C_total = 100.1nF (negligible effect here, but matters at lower R values).

Exercise 2: Signal Integrity Analysis

You are routing an SPI bus at 50 MHz (clock frequency, tr ≈ 2ns) between an STM32 MCU and an external flash memory on a 4-layer PCB. The trace length is 8cm on Layer 1 with Z0 = 50Ω.

  1. Is 8cm longer than the critical trace length for a 2ns rise time? Show your calculation.
  2. The flash memory’s MISO pin has an input capacitance of 8pF. Model this as a load impedance at 50 MHz and calculate the reflection coefficient. Will you see ringing?
  3. Design a series termination resistor value for the MCU’s MOSI output. The STM32 GPIO output impedance is approximately 25Ω in high-speed mode. What resistor value achieves a matched source termination?
  4. Calculate the one-way propagation delay for the 8cm trace in FR4. Is there a timing concern for SPI at 50 MHz (20ns clock period)?

Hint: Critical length = 2ns × 1.5e8 / 10 = 3cm. 8cm > 3cm → YES, transmission line effects matter. Flash capacitive load at 50MHz: Z_L = 1/(2π×50e6×8e-12) = 398Ω. Γ = (398-50)/(398+50) = +0.78 → severe ringing. Series termination: R_term = Z0 - Z_out = 50 - 25 = 25Ω (use 22Ω standard). Propagation delay = 8cm / 1.5e8 = 0.53ns (fine for 20ns period).

Exercise 3: PDN Analysis & Decoupling

Your STM32F4 MCU draws 100mA steady state but has current transients of 300mA when toggling 16 GPIO pins simultaneously (driving LEDs). The 3.3V rail has 5% ripple tolerance. You currently have one 10µF bulk capacitor near the LDO and one 100nF MLCC on each of the MCU’s 4 VDD pins.

  1. Calculate the PDN target impedance for the 300mA transient with 5% ripple on 3.3V.
  2. Using the decoupling simulation code, determine if four 100nF MLCCs in parallel meet this target at 100 MHz (the MCU’s clock frequency). Assume ESR=10mΩ, ESL=0.5nH per cap.
  3. The GPIO toggle frequency is 1 MHz. At this frequency, what is the combined impedance of the 10µF bulk + four 100nF MLCCs? Is it below the target?
  4. Propose a complete decoupling strategy (specific capacitor values, quantities, and placement) to keep PDN impedance below the target from 10 kHz to 200 MHz.

Hint: Target Z = 165mV / 300mA = 0.55Ω = 550mΩ. Four 100nF in parallel: Z at 100MHz ≈ 0.03Ω/4 = 7.5mΩ (well below target). At 1MHz: Z_100nF×4 ≈ 0.4Ω, Z_10µF ≈ 0.016Ω → parallel ≈ 16mΩ (fine). Strategy: keep existing caps + add 2× 100pF (0402) closest to VDD pins for >100MHz coverage.

Simulation Report Tool

Document your simulation results with this tool for design reviews and compliance records.

Simulation Report Generator

Enter your simulation parameters and results to generate a professional report. Download as Word, Excel, or PDF.

Draft auto-saved

Conclusion & Next Steps

Simulation is your safety net against expensive board re-spins. You now know how to run SPICE transient and AC analysis for power supplies and filters, evaluate signal integrity with reflection coefficients and critical length calculations, and verify power delivery network impedance with multi-cap strategies.

Key takeaways: (1) Simulate every power supply before layout. (2) Know your critical trace length — anything longer needs impedance control. (3) Use 4 capacitor values in parallel for broadband PDN filtering. (4) Document simulation results for design reviews.

Next in the Series

In Part 7: DFX (Design for Excellence), we’ll make your design production-ready — fabrication constraints, panelization, assembly orientation rules, fiducial placement, stencil aperture design, and test point strategies for manufacturing at scale.