AugmentClaude

gm/ID Transistor Designer

Characterize and size MOSFETs using gm/ID methodology with ngspice simulations.

Installation

  1. Make sure Claude is on your device and in your terminal.

    Skills load from ~/.claude/skills/ when Claude Code starts up — so you need it on your machine first. If you don't have it yet, install it once with the command below, then run claude in any terminal to verify.

    One-time setup
    npm i -g @anthropic-ai/claude-code

    Already have it? Skip ahead.

  2. Paste into Claude Code or into your terminal.

    This copies the whole skill folder into ~/.claude/skills/gmoverid-arcadia-1/ — the SKILL.md plus any scripts, reference docs, or templates the skill ships with. Safe default: works for every skill.

    Faster alternative (instruction-only skills)

    Skips the clone and grabs only the SKILL.md file. Don't use this if the skill ships Python scripts, reference markdowns, or asset templates — they won't be downloaded and the skill will fail when it tries to load them.

    Quick install (SKILL.md only)
    Sign up to copy
  3. Restart Claude Code.

    Quit and reopen Claude Code (or any other agent that loads from ~/.claude/skills/). New skills are picked up on startup.

  4. Just ask Claude.

    Skills auto-activate when your request matches the skill's description — no slash command needed. Trigger phrases live in the skill's own frontmatter; you can read them in the “What this skill does” section above.

Prefer to read the source first? Open on GitHub.

When Claude uses it

gm/ID transistor characterization and design methodology, based on ngspice + Python. Two independent workflows: (1) Characterization — generates three standard curve sets for any MOSFET model: gate capacitance (Cgg/Cgs/Cgd/Cgb vs Vgs), gm/ID four-quadrant characteristics (gm/Id vs Vov, Id/W vs gm/Id, fT vs gm/Id, gm·ro vs gm/Id), and IV characteristics (linear/log Id vs Vov, output curves). Supports 180 nm single-node and 45/22 nm HP multi-node flows with built-in PTM model files (180/45/22 nm) — no extra downloads required. (2) Design — the GmIdTable class builds a lookup table from simulation data (cached to logs/cache/) and provides lookup(), size(), size_from_ft(), size_from_gmro() APIs for NMOS/PMOS transistor sizing using the gm/ID methodology. Only depends on the ngspice skill. Use this skill when setting up or extending a gm/ID characterization project, generating characteristic curves, interpreting design curves, or sizing transistors by the gm/ID method.

What this skill does

gm/ID Characterization and Design Skill

Important — do not modify skill files during normal use. All code edits, new scripts, plots, and simulation outputs should go into the user's project working directory (outside .claude/), not into this skill folder. Only modify the skill assets (assets/, SKILL.md, references/) when the user explicitly asks to improve or extend the skill itself.

Dependency: ngspice skill (netlist execution, wrdata parsing). Model files are built in — the transistor-models skill is not required.

Asset Files

assets/
├── simulate_gmoverid.py   — ngspice simulation engine, data extraction, analytical caps, MODEL_INFO registry
├── plot_gmoverid.py       — all matplotlib plotting functions
├── run_gmoverid.py        — 180 nm single-node orchestration (NMOS/PMOS + channel-length sweep)
├── run_multinode.py       — multi-node orchestration (45/22 nm HP)
├── design_gmoverid.py     — GmIdTable lookup/sizing API + print_op()
├── models/                — built-in PTM model files (ready to use)
│   ├── nmos180.lib        — 180 nm BSIM3v3 (VDD = 1.8 V)
│   ├── pmos180.lib
│   ├── nmos45hp.lib       — 45 nm HP BSIM4 (VDD = 1.0 V)
│   ├── pmos45hp.lib
│   ├── nmos22hp.lib       — 22 nm HP BSIM4 (VDD = 0.8 V)
│   └── pmos22hp.lib
└── netlist/
    ├── gmoverid_vgs.cir.tmpl       — NMOS Vgs sweep (fixed Vds)
    ├── gmoverid_vds.cir.tmpl       — NMOS Vds sweep (fixed Vgs)
    ├── gmoverid_pmos_vsg.cir.tmpl  — PMOS |Vsg| sweep (fixed |Vsd|)
    └── gmoverid_pmos_vsd.cir.tmpl  — PMOS |Vsd| sweep (fixed |Vsg|)

Built-in models are from PTM — Arizona State University (ptm.asu.edu), free for academic research. When citing, use: W. Zhao and Y. Cao, "New Generation of Predictive Technology Model for Sub-45 nm Early Design Exploration," IEEE Trans. Electron Devices, vol. 53, no. 11, pp. 2816–2823, Nov. 2006. doi: 10.1109/TED.2006.884077. For nodes beyond the three built-in ones, install the transistor-models skill (full PTM library, requires manual MODEL_INFO configuration) or download from mec.umn.edu/ptm and copy the .lib file into the project's models/ directory.


Workflow 1: Characterization (Simulation + Plotting)

Deployment

  1. Copy all assets (including the models/ subdirectory) to <project>/
  2. Create empty directories plots/ and logs/
  3. Run python run_gmoverid.py (180 nm) or python run_multinode.py (HP multi-node)

For additional nodes, simply copy the extra .lib file into <project>/models/.

All paths resolve automatically via Path(__file__).resolve().parent — no path configuration needed.

Three Standard Plot Sets (per model)

SetFunctionOutput file
Gate capacitanceplot_caps()gmoverid_caps_{model}_L{node}nm.png
gm/ID four-quadrantplot_main()gmoverid_{model}_L{node}nm.png
IV characteristicsplot_iv()gmoverid_iv_{model}_L{node}nm.png

gm/ID four-quadrant layout (plot_main, 2×2):

(0,0) gm/Id [V⁻¹] vs Vov     | (0,1) Id/W [uA/um] vs gm/Id  (log Y)
(1,0) fT [GHz]    vs gm/Id   | (1,1) gm·ro        vs gm/Id
  • All four panels use Vds as the curve parameter (VDS_LIST)
  • gm/Id X-axis: xlim = [4, 24], one grid division per 2 V⁻¹
  • Panels (0,1), (1,0), (1,1) apply _fall_mask(gmid) before plotting — the gm/ID array is double-valued (same gm/ID appears on the subthreshold rising side and the inversion falling side); only the falling (inversion) side is kept to prevent curve fold-back. Panel (0,0) is exempt because its X-axis is Vov, which is monotonic.

Adding a New Technology Node

  1. Copy the model .lib into models/ (download from mec.umn.edu/ptm or install the transistor-models skill)
  2. Add an entry to MODEL_INFO in simulate_gmoverid.py (see conventions.md §3)
  3. Add an entry to NODE_CFG in run_multinode.py

Plotting Conventions (required when creating new figures)

When generating figures for a new project or plotting for a design report, follow the style of the existing figures produced by this skill.

Format requirements:

  • Never call plt.show(); always use fig.savefig(path, dpi=150, bbox_inches='tight') and save to plots/
  • Colors and line styles: cycle through COLORS/LSTYLE from plot_gmoverid.py in order (blue solid, orange dashed, green dash-dot, purple dotted)
  • X-axis for gm/ID: always xlim = [4, 24] with one tick per 2 V⁻¹; Y-axis ylim(bottom=0)
  • Fold-back prevention: whenever gm/ID is the X-axis, prepend _fall_mask(gmid) to the boolean mask. The gm/ID vs Vgs curve peaks and then descends — both sides can fall within [4, 24], causing matplotlib to draw a fold-back. _fall_mask discards the subthreshold rising side (before the peak); only the inversion falling side is plotted. This rule applies to plot_main panels (0,1)/(1,0)/(1,1) and to the equivalent panels in plot_comparison.
  • Titles and axis labels: use ASCII + LaTeX (e.g. $g_m/I_D$); do not write Chinese characters directly in matplotlib labels
  • µ (U+00B5) fails to render in some terminals and fonts — always use u in axis labels (e.g. uA/um, W=10um) or LaTeX $\\mu$; use Unicode µ only when the user explicitly requests it

Chinese font warning: matplotlib does not include Chinese fonts by default; Chinese characters render as boxes (□□). If Chinese is needed, add at the top of the script:

import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'DejaVu Sans']
matplotlib.rcParams['axes.unicode_minus'] = False

On Windows prefer Microsoft YaHei; on Linux/macOS verify the font is installed, otherwise boxes still appear. The most robust approach is to use only ASCII/LaTeX labels and avoid font dependencies entirely.


Workflow 2: Design (Lookup-Table Sizing)

Core Idea of the gm/ID Methodology

gm/ID (transconductance efficiency) is the pivot quantity linking circuit specifications to device dimensions.

Traditional design relies on long-channel model equations (gm = 2Id/Vov) to compute device sizes; errors are severe in advanced nodes (≤ 180 nm). The gm/ID method abandons equations in favor of simulation-generated design charts (lookup tables), using gm/ID as the single independent variable to express all key device performance parameters:

gm/ID  ──►  Id/W   (current-density curve → determines W)
       ──►  fT     (transit frequency → determines speed)
       ──►  gm·ro  (intrinsic gain → determines gain ceiling)
       ──►  Vgs    (uniquely determines the bias point)

All four curves are independent of transistor width W — devices of different W share exactly the same Id/W, fT, and gm·ro values at the same gm/ID point. This is the foundation of the methodology: the design chart needs to be generated only once (at unit width), and it applies directly to any W.

gm/ID is the trade-off axis for three design objectives:

Design priorityDirection of gm/IDReason
High speed (fT↑)Low gm/ID (strong inversion)High Vov → fast
High gain (gm·ro↑)High gm/ID (weak/moderate inversion)Closer to subthreshold
Low power (Id↓, same W)High gm/IDId/W decreases as gm/ID increases
Minimum area (W↓, same Id)Low gm/IDId/W decreases as gm/ID increases

Note: area and power optimization point in opposite directions — this is the central trade-off in gm/ID design.


Design Flow (Five Steps)

① Choose topology → ② Set L → ③ Choose gm/ID → ④ Derive gm / Id → ⑤ Look up Id/W → get W

① Choose topology Select the circuit structure (common-source, differential pair, cascode, common-gate, etc.) based on gain, bandwidth, and swing requirements.

② Set channel length L

  • Need high speed (high fT) → choose minimum L
  • Need high gain (high gm·ro) → increase L moderately (each doubling of L raises gm·ro by roughly 2–4×, with a corresponding fT reduction)
  • Verify feasibility first: tbl.lookup('gmro', gmid_target) to check the upper bound; if unsatisfied, increase L before considering cascode or multi-stage topologies
  • With a PMOS load, also verify PMOS ro: effective gain = gm_n × (ro_n ∥ ro_p)

③ Choose gm/ID Select the trade-off point on the fT–gm/ID and gm·ro–gm/ID curves based on the design priority:

tbl = GmIdTable('nmos45hp', W=1.0, L=0.045, vds=0.5)

# Check boundary values before deciding
print(f"fT   @ gmid=6  : {tbl.lookup('ft',   6.0)/1e9:.1f} GHz")
print(f"fT   @ gmid=15 : {tbl.lookup('ft',  15.0)/1e9:.1f} GHz")
print(f"gmro @ gmid=6  : {tbl.lookup('gmro',  6.0):.1f}")
print(f"gmro @ gmid=15 : {tbl.lookup('gmro', 15.0):.1f}")

④ Derive the required gm from circuit specs, then compute Id

# Example: BW and gain constraints → gm (ro-aware, see design example section)
Rout = 1 / (2 * 3.14159 * BW * CL)   # RL∥ro, set by bandwidth
gm   = Av / Rout                       # set by gain
Id   = gm / gmid                       # set by gm/ID

⑤ Look up Id/W to get W, round to 100 nm grid

id_w    = tbl.lookup('id_w', gmid)              # uA/um (W-independent)
W_exact = Id / (id_w * 1e-6)                   # um
W       = round(W_exact / 0.1) * 0.1           # round to 100 nm
# W     = math.ceil(W_exact / 0.1) * 0.1       # or round up (conservative margin)

After rounding, recompute Id = W × id_w and verify Av and BW; a ΔW < 5% deviation is usually negligible.


API Reference: GmIdTable

from design_gmoverid import GmIdTable, print_op

# First call: runs ngspice automatically and caches to logs/cache/ (JSON)
# Subsequent calls: reads from cache, ~0.05 s
tbl = GmIdTable('nmos180', W=10.0, L=0.18, vds=0.9)

Constructor parameters:

ParameterTypeDefaultDescription
modelstrKey in MODEL_INFO, e.g. 'nmos180', 'pmos45hp'
WfloatSimulation reference width [um] (results are W-independent; any value works)
LfloatChannel length [um]
vdsfloatVDD/2Fixed Vds (NMOS) or |Vsd| (PMOS) during Vgs sweep [V]
force_resimboolFalseIf True, ignores cache and re-runs simulation

Single-quantity lookup (W-independent, depends only on gm/ID):

tbl.lookup('id_w', gmid)   # Id/W [uA/um]  <- use this to compute W
tbl.lookup('ft',   gmid)   # transit frequency fT [Hz]
tbl.lookup('gmro', gmid)   # intrinsic gain gm·ro
tbl.lookup('vgs',  gmid)   # Vgs (or |Vsg|) [V]  <- bias point
tbl.lookup('vov',  gmid)   # overdrive voltage Vov [V]
tbl.lookup('gm',   gmid)   # transconductance [S] (at reference width W)

Sizing: fix gm/ID + one constraint

op = tbl.size(gmid=15.0, Id=100e-6)   # given Id, solve for W
op = tbl.size(gmid=15.0, W=20.0)      # given W, solve for Id
op = tbl.size(gmid=15.0, gm=1.5e-3)   # given gm, solve for Id and W
print_op(op)

Constrained sizing: auto-search (highest gm/ID = lowest current)

op = tbl.size_from_ft(8e9,  W=20.0)    # fT >= 8 GHz, fixed W
op = tbl.size_from_gmro(35, Id=50e-6)  # gm·ro >= 35, fixed Id
  • size_from_ft: suited for known-width, speed-constrained scenarios (LNA transconductor, OTA GBW)
  • size_from_gmro: suited for high-gain stages (prefer fixing W to avoid excessively large W in weak inversion)

Keys returned by size():

model, L_um, W_um, Id_A, Vgs_V, Vov_V, gmid, gm_S, ft_Hz, gmro, id_w_Apm

Typical gm/ID Design Parameters by Node

nmos180 (Vds = 0.9 V, L = 180 nm)

gm/ID [V⁻¹]Id/W [uA/um]fT [GHz]gm·roTypical use
5–842–8120–2527–36High-speed circuits, sampling switches
10–1220–2915–1839OTA output stage, drivers
13–168–179–1339–46OTA input differential pair (balanced)
18–203–64–653Low-power analog, voltage references

nmos45hp / nmos22hp (HP, minimum L)

Nodegm/ID [V⁻¹]Id/W [uA/um]fT [GHz]gm·roNotes
45 nm HP6–10150–300200–4006–8Strong CLM, low gain — ro must be considered
22 nm HP6–10200–500400–7003–4Very strong DIBL, extremely low gain

Vds has a minor effect on Id/W (advanced nodes have lower output impedance): ignore it during initial design, then fine-tune after simulation.


Design Example: 45 nm HP Common-Source Amplifier

Specifications (from textbook §5.2.1, 40 nm process, using PTM 45 nm HP as surrogate model):

SpecificationValue
VDD1.1 V
Low-frequency voltage gain Av2 (linear, i.e. 6 dB)
−3 dB bandwidth BW100 MHz
Load capacitance CL10 pF
Total current Id≤ 2 mA
Channel length L45 nm (minimum gate length)
Design targetgm/ID = 10 V⁻¹ (balanced speed vs. power)

1. Derive Design Constraints (ro-aware)

The gain equation includes the ro term and cannot be neglected:

|A_DC| = gm·(RL ∥ ro)

1/|A_DC| = 1/(gm·RL) + 1/(gm·ro)

=> gm·RL = 1 / (1/Av − 1/(gm·ro))

For 45 nm HP, intrinsic gain gm·ro ≈ 7 (confirmed via tbl.lookup('gmro', gmid)). Substituting:

gm·RL = 1 / (1/2 − 1/7) ≈ 2.80

Bandwidth determines the total output-node impedance (RL ∥ ro), i.e. the actual Rout:

Rout = RL ∥ ro = 1 / (2pi × BW × CL)
     = 1 / (2pi × 100 MHz × 10 pF) ≈ 159 Ohm

gm = Av / Rout = 2 / 159 ≈ 12.6 mA/V

RL = gm·RL / gm = 2.80 / 12.6 mS ≈ 222 Ohm

Why not simply set RL = Rout? Rout = 159 Ω is RL∥ro, not RL itself. RL must be larger than Rout and is back-calculated from the gain equation using the gm·ro term.

2. Size with GmIdTable

from design_gmoverid import GmIdTable
import math

VDD = 1.1;  Av = 2.0;  BW = 100e6;  CL = 10e-12

tbl = GmIdTable('nmos45hp', W=1.0, L=0.045, vds=0.5)

gmid = 10.0
gmro = tbl.lookup('gmro', gmid)   # => 7.11
id_w = tbl.lookup('id_w', gmid)   # => 155.4 uA/um
vgs  = tbl.lookup('vgs',  gmid)   # => 0.499 V  (bias Vgs)
vov  = tbl.lookup('vov',  gmid)   # => 0.244 V

# Step 1: derive gm and RL (ro-aware)
Rout   = 1 / (2 * 3.14159 * BW * CL)   # 159 Ohm = RL||ro
gm_RL  = 1 / (1/Av - 1/gmro)           # 2.80 (gain constraint including ro)
gm     = Av / Rout                      # 12.6 mA/V
RL     = gm_RL / gm                     # 222 Ohm

# Step 2: compute Id and W
Id      = gm / gmid                     # 1.26 mA
W_exact = Id / (id_w * 1e-6)           # 8.09 um
W       = round(W_exact / 0.1) * 0.1   # => 8.1 um (100 nm grid)

# Step 3: verify with rounded W
Id_r  = W * id_w * 1e-6                # 1.259 mA
gm_r  = Id_r * gmid                    # 12.59 mA/V
ro_r  = gmro / gm_r                    # 565 Ohm
Av_r  = gm_r * (RL * ro_r / (RL + ro_r))  # 2.00 ✓
Vd_DC = VDD - Id_r * RL                # 0.821 V  (margin 577 mV >> Vov 244 mV ✓)

3. Design Summary

ParameterValue
gm/ID10 V⁻¹
W / L8.1 um / 45 nm
Id1.26 mA (< 2 mA ✓)
gm12.6 mA/V
gm·ro7.11
RL222 Ohm
Av (verified)2.00 ✓
Vgs (bias)0.499 V
Vd_DC0.821 V

4. Post-Design Simulation (hand off to ngspice skill)

With W, RL, and Vgs in hand, use the ngspice skill to build a .control block netlist and simulate:

  • DC operating point: verify @m1[id], @m1[gm], @m1[gds] against design values
  • AC frequency response: ac dec 200 1e5 1e10 → read vdb(vout) → verify low-frequency gain and −3 dB frequency
  • Plotting: save frequency-gain data with wrdata, plot a Bode magnitude response using matplotlib

Self-Validation

Two complementary checks — run both after generating characterization plots.

Step 1 — Numerical self-check

python validate_gmoverid.py [model] [L_um]
python validate_gmoverid.py                    # nmos180 @ 180 nm
python validate_gmoverid.py nmos45hp 0.045

Five scalar tests, each prints PASS / FAIL:

#TestPass criterionFailure meaning
1Weak-inversion limitpeak gm/ID in [25, 32] V^-1gm extraction error near Id ≈ 0
2ID/W monotonicityzero non-monotone stepsInterpolation oscillation in gm or Id
3aL-doubling gaingmro(2L)/gmro(L) ≥ 1.5Model ignores CLM
3bL-doubling fTfT(2L)/fT(L) in [0.15, 0.70]Cgg scaling wrong
4fT×gm/ID peakpeak at gm/ID in [8, 18] V^-1Cgg or gm mismatch
5Vds sensitivitygmro change ≥ 8% across 0.25–0.75 VDDModel ignores channel-length modulation

For physics derivation and failure diagnosis see references/validation.md.

Step 2 — Visual inspection by LLM

Generate the four-quadrant plot, then show it to Claude and ask for a physics assessment. The expected trends for each panel are listed below — use them as the inspection checklist.

Panel (0,0) — gm/ID vs Vov

ZoneExpected trendTypical values
Vov < 0 (subthreshold)gm/ID approaches a constant ceiling from below25–32 V^-1 (= 1/(n·Ut), n=1.2–1.5)
Vov ≈ 0 (threshold)smooth peak, then monotone descentpeak ≈ 25–32 V^-1
Vov > 0 (strong inversion)follows 2/Vov (dashed reference line) closelydrops to ~5 V^-1 at Vov=0.4V

Red flags: peak > 35 (gm noise at low Id), plateau that never decays (missing strong-inversion region), kink at Vov=0 (Vth extraction error).

Note: for HP minimum-L nodes, DIBL raises the slope factor n toward 1.4–1.5, so the subthreshold ceiling legitimately sits closer to 25 V^-1 rather than 32 V^-1 — this is correct, not a model defect.

Panel (0,1) — Id/W vs gm/ID (log Y)

FeatureExpected
Directionstrictly decreasing left to right (strong→weak inversion)
Shape on log scaleapproximately linear (exponential decay in weak inversion)
Rangespans ≥ 2 decades across gm/ID = [4, 24]
Multiple Vds curvesnearly overlapping (Id/W is weakly Vds-dependent in saturation)

Red flags: any upward hook (fold-back from subthreshold rising side — fixed by _fall_mask), flat segment (resolution too coarse), curves widely separated by Vds (device not in saturation).

Panel (1,0) — fT vs gm/ID

FeatureExpected
Directionmonotonically decreasing left to right
Shaperoughly follows a power law; steeper decay toward high gm/ID
Magnitude180nm: 5–30 GHz; 45nm HP: 100–400 GHz
Multiple Vds curvesnearly overlapping (fT is Vds-insensitive in saturation)

Red flags: fT increases with gm/ID (sign inversion in gm or Cgg), non-monotone wiggles (ngspice convergence issue near threshold), fT > 1 THz or < 1 GHz at reasonable bias (Cgg extraction error).

Panel (1,1) — gm·ro vs gm/ID

FeatureExpected
Directiongenerally increasing left to right (weak inversion has higher gain)
Magnitude180nm: 20–60; 45nm HP min-L: 5–15
Vds dependencecurves separated — higher Vds → lower gmro (stronger CLM)
Shapesmooth, no kinks; may plateau in strong inversion

Red flags: completely flat across all gm/ID (CLM ignored), gmro > 200 at moderate gm/ID for short-channel nodes (gds underestimated), kinks at specific Vgs points (sparse Vds-sweep interpolation artefact — use vgs_gds_results to enable finite-difference gds path).

Interpreting LLM visual feedback

LLM image analysis is powerful for shape and smoothness but requires physical context to interpret correctly:

  • "Peak below BJT limit 38.6 V^-1" — expected; MOSFETs have n > 1. Correct ceiling is 1/(n·Ut) ≈ 25–32 V^-1.
  • "Curves widely separated in panel (0,1) or (1,0)" — check Vds values; if all are well into saturation the separation should be < 20%.
  • "gmro is very low (5–10)" — normal for HP minimum-L nodes; not a defect.
  • "Curve does not reach weak inversion" — increase Vgs sweep range or lower id_thresh in sweep_vgs.

Reference Documents

See references/conventions.md for full details:

  • §1–5 Project structure, symbol conventions, MODEL_INFO, netlist templates, data-dict keys
  • §6–7 Sweep configuration constants (NODE_CFG), plotting conventions and figure list
  • §8–9 Physical sanity-check values, common errors and fixes
  • §10 Extending the skill (new nodes, new plot types, new channel lengths)
  • §11 Full design API reference (GmIdTable, print_op, cache naming, unit conventions)

Related skills