Skip to content

analog: sar_cdac.t27 -- the SAR ADC split capacitive DAC with its 1-unit bridge, charge redistribution against ngspice (Closes #10540) - #10575

Merged
gHashTag merged 1 commit into
masterfrom
claude/analog-m4a-cdac-10540
Oct 18, 2026
Merged

gHashTag merged 1 commit into
masterfrom
claude/analog-m4a-cdac-10540

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10540

M4a of the SAR ADC milestone (#10524, epic #10486). Adds specs/analog/sar_cdac.t27 (+ seal) and two ngspice decks in specs/analog/decks/. No board top, no PDK capacitor model.

What it is

One half of Diff_cap_DAC of the golden SAR ADC deck (read at run time, GPL-2.0, not vendored): 31 LSB units on net1 (Bit_1..Bit_5 = 1, 2, 4, 8, 16, deck lines 529-559), a 1-unit bridge (line 560), 31 MSB units on Vout (Bit_6..Bit_10, lines 561-591). Unit counts and line numbers are pinned in the spec and checked (FR-001).

Each bottom-plate switch event is M1's step (use analog::linear, nothing copied) with D = 0 and N = K = C^-1 C_b. K is derived in the tests from the counts two ways (adjugate and the closed form of the split array, agree to 1e-15) and stored as Q.24 words. A code is ten events, Bit_10 first, each plate moving +-VCM (0.75 V) from the sampled state, as DAC_control / neg_bottom_plate_logic do: every plate rests at VCM, then goes once to VDD or 0 V. The N half is the P half reversed. The comparator is not modelled; the code is an input.

Correction to the issue's premise (please read)

The issue expects the deck's 1-unit bridge to carry a half-to-half mismatch against an "ideal 32/31 bridge". The measurement says the deck's bridge IS the ideal one: the ideal bridge is CL/31, which is 1 unit for the deck's 31-unit LSB array (no dummy unit) and 32/31 only for an array with a 32nd, dummy unit to ground (the textbook split array). For the deck D = 3131 + 1(31+31) = 1023 and every Vout ratio is exactly 2^(j-1)/1023. The negative control "ideal bridge makes the error vanish" therefore holds for the dummy-unit array, not for the deck's; both are in the tests.

Bridge error (FR-002), all 1024 codes of one half

max where
bend (INL about the line through codes 0 and 1023) 0 (< 1e-9 LSB) every code
gain error vs the nominal 10-bit half, (2c-1023)/2046 LSB 0.5 LSB (0.73 mV) code 0 (-0.5) and code 1023 (+0.5)

Cause: the bridge in series with the 31-unit array is 31/32 of a unit, so the top plate sees 1023/32 units instead of 32 and the staircase spans exactly VDD where a nominal half spans 1023/1024 of it.

Comparisons

  • fixed point vs f64 closed form (VDD c/1023): max 1.74 units of 2^-24 V (1.04e-7 V, 7.1e-5 LSB), Vout first at code 224, net1 first at code 1016; ends land one unit outside 0 / 1.5 V
  • ngspice-47, ideal 100 fF capacitors, all 1024 codes: 1.29e-12 V from the closed form (its own drift, largest at code 1023), 1.74 units from the fixed point, each code asserted on its own
  • differential pair (16 codes: ends, every single-bit code, 511/512/513, 341, 682; P sampled 0.875 V, N 0.625 V): each half within 2 units of ngspice, VP-VN within 4 units of the closed form and 3e-12 V of ngspice's
  • the ngspice values are a recorded measurement (a test cannot run ngspice), kept honest by the 1e-12 V closed-form bound; how they were read is in the spec and the deck headers

Negative controls

  • Bit_8 = 3 units: all 20 stored words differ, bend 28.9 LSB at code 128, ngspice 42 mV off; a real copy of the spec with that count fails 7 of 12 tests
  • one stored word off by one: 6 of 12 fail; one ngspice table value off by 1 uV: the per-code ngspice test fails
  • 32/31 bridge on the deck's array: bends 0.94 LSB (first at code 31), ngspice 1.37 mV from it; 32/31 with the dummy unit: bend 0, gain error 0; 1-unit bridge with the dummy: bend 0.91, gain 0.93 LSB
  • Bit_6 on net1, a 2-unit bridge, Bit_10 = 15 units: stored words differ

Gates

  • t27c test-report specs/analog/sar_cdac.t27: 12 tests, 12 pass, 0 FAIL, vacuous passes 0 of 12 (runtime asserts per test 29, 21, 6, 17, 4100, 1032, 1034, 2067, 80, 1, 10, 16); tri test 12/12
  • t27c seal --save then --verify: all hashes MATCH, saved with the zig cache set, 0 home paths in the seal
  • python3 -I tools/dupe_scan.py: ok; tri types ratchet: CLEAN 107/107 (structs are CdacNodes and CdacWorst, unique names)
  • t27b-native-ratchet red with only UNLISTED rows for the new spec is expected (spec PRs do not edit the ledger, t27b ledger steward: the rules and the job card, so spec PRs stop editing the ledger (Closes #8654) #8656)

Not covered

No IHP capacitor value or mismatch, parasitics, 4 fF loads, switch charge injection, settling or leakage; no comparator, SAR logic, eleventh decision or output code; no board. Differential spot codes leave the rails at the extremes (-0.125 V, 1.625 V) in the ideal linear model.

🤖 Generated with Claude Code

…nit bridge, charge redistribution against ngspice (Closes #10540)

M4a of the SAR ADC milestone (#10524, epic #10486). One half of Diff_cap_DAC of the
golden SAR ADC deck: 31 LSB units on net1, a 1-unit bridge, 31 MSB units on Vout,
unit counts and deck lines (529-591) pinned in the spec. Each bottom-plate switch
event is M1's step (specs/analog/linear.t27) with D = 0 and N = K = C^-1 C_b, the
Q.24 charge-transfer ratios derived in the tests from the counts two ways (adjugate
and closed form) and stored as words. A code is ten events, Bit_10 first, plates
moving +-VCM from the sampled state.

Result for all 1024 codes of one half:
- the deck's 1-unit bridge is the ideal bridge for its 31-unit LSB array (no dummy
  unit): every Vout ratio is exactly 2^(j-1)/1023, INL 0
- bridge-induced error is a gain term: (2c-1023)/2046 LSB against the nominal
  10-bit half, max 0.5 LSB at codes 0 and 1023 (first at code 0)
- arithmetic error vs the f64 closed form: 1.74 units of 2^-24 V (7.1e-5 LSB)
- ngspice-47 with ideal capacitors (decks sar_cdac_half.cir, sar_cdac_diff.cir):
  1.29e-12 V from the closed form, 1.74 units from the fixed point, every code
- differential pair checked at 16 codes
- the 32/31 bridge is ideal only with a dummy 32nd unit: with it bend 0 and gain
  error 0; on the deck's array it bends 0.94 LSB. Bit_8 with 3 units fails 7 of 12
  tests (28.9 LSB of bend, 42 mV from ngspice)

12 tests, 0 vacuous, sealed (all hashes MATCH).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) October 18, 2026 17:44
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 18:39:47 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 45
PRs with All Checks Green 5
READY 0
FAILING 45
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 45 + 0 + 0 = 45, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

analog M4a: the SAR ADC capacitive DAC -- split array with a 1-unit bridge capacitor, charge redistribution against ngspice

2 participants