Design it, then break it: a DAC output buffer
Design a two-stage op-amp buffer for the E8.3 DAC to a settling, accuracy and offset spec, sign it off across corners and temperature, then inject faults and write the bench lines that catch each one.
- Lesson
- E8.4
- Time
- 45 min
- Runs on
- ngspice
- Check
- 5 questions
A 6-bit DAC with a near-perfect ladder sent a new code every 100 ns. Its buffer, E6.4's OPA-B, had passed its DC tests: within 1 mV of its input from 0.6 V to 1.2 V. Yet the sample after a full-scale fall came out 155 mV low, 16.5 LSB.
- v(dac)
- v(out)
- Time 199 nsv(dac) = 1.191 V · v(out) = 1.19 V
End of code 63: the rise has settled, −0.43 mV off.
- Time 275 nsv(dac) = 600 mV · v(out) = 398 mV
After the fall the output dives to 398 mV, far below the 600 mV it should reach.
- Time 299 nsv(dac) = 600 mV · v(out) = 445 mV
The next sample: still 155 mV low.
Read the plot as a table
| Time | v(dac) | v(out) |
|---|---|---|
| 0 s | 600 mV | 599 mV |
| 50 ns | 600 mV | 599 mV |
| 100 ns | 600 mV | 599 mV |
| 150 ns | 1.191 V | 1.195 V |
| 199 ns | 1.191 V | 1.19 V |
| 200 ns | 1.19 V | 1.19 V |
| 250 ns | 599.4 mV | 659.3 mV |
| 275 ns | 600 mV | 398 mV |
| 299 ns | 600 mV | 445 mV |
| 300 ns | 601.3 mV | 447.5 mV |
| 350 ns | 900 mV | 901.4 mV |
| 400 ns | 900 mV | 899.9 mV |
Measured on ngspice 42, tt, 27 °C.
A buffer is signed off for the steps it must make in the time it is given, at every corner, and the bench must be able to fail.
The brief
This capstone has two halves. First you design a buffer to a spec and sign it off. Then you swap roles: faults are injected, and you write the bench lines that catch them.
| Item | Spec |
|---|---|
| DAC | The E8.3 ladder, 6 bits, 1.41 × 10 µm units, between references VL and VH that you choose |
| Buffer | OPA-B (E5.5) as a unity-gain follower, any sizing, its own 20 µA bias |
| Load | 2 pF |
| Settling | within ±½ LSB of the final level 70 ns after any code change (a 10 MHz update leaves 30 ns to sample) |
| DC error | within ±½ LSB at every code |
| Stability | phase margin of at least 55° |
| Offset | 3σ of 20 Monte Carlo dies within 1 LSB |
| Where | all five FET corners at −40, 27 and 125 °C; then the least supply current |
The reference design below meets every line; its numbers are measured, not targets.
Read the circuit as text
- IB current source (20 µA): + →
VDD, − →n1 - MB NMOS transistor (8/1): gate →
n1, drain →n1, source →0 - M3 PMOS transistor (32/2): gate →
n2, source →VDD, drain →n2 - M4 PMOS transistor (32/2): gate →
n2, source →VDD, drain →n3 - M1 NMOS transistor (20/2): gate →
n4, drain →n2, source →n5 - M2 NMOS transistor (20/2): gate →
n6, drain →n3, source →n5 - M5 NMOS transistor (8/1): gate →
n1, drain →n5, source →0 - M6 PMOS transistor (128/1): gate →
n3, source →VDD, drain →n7 - M7 NMOS transistor (32/1): gate →
n1, drain →n7, source →0 - R_z resistor (5 kΩ): pin 1 →
n3, pin 2 →n8 - C_c capacitor (1 pF): pin 1 →
n8, pin 2 →n7 - C_L capacitor (2 pF): pin 1 →
n7, pin 2 →0 - − inn port: terminal →
n4 - + inp port: terminal →
n6 - out port: terminal →
n7
W/L in µm. Bodies: NMOS to ground, PMOS to VDD. C_c = 1 pF and R_z = 5 kΩ, as E6.4 left them.
Where the input can go
An NMOS input pair needs room under it: the tail transistor M5 must stay saturated (E5.2 Common mode: rejection and the input range). Sweep the buffer's input and watch both its DC error and M5's current.
- v(out) − v(in)
- tail current
- Input 600 mVv(out) − v(in) = -950.5 µV · tail current = 4.42 µA
At 0.6 V the error is only −0.95 mV, but M5 carries 4.4 µA of its 19.5 µA: the first stage is starved.
- Input 816.7 mVv(out) − v(in) = -160.9 µV · tail current = 17.59 µA
The tail reaches 90 % of its 1.2 V current at 817 mV.
- Input 1.278 Vv(out) − v(in) = -3.125 mV · tail current = 19.66 µA
At the top the error passes −½ LSB (of a 0.4 V range) at 1.278 V.
Read the plot as a table
| Input | v(out) − v(in) | tail current |
|---|---|---|
| 400 mV | -2.93 mV | 64.65 nA |
| 600 mV | -950.5 µV | 4.42 µA |
| 800 mV | -176.9 µV | 17.14 µA |
| 816.7 mV | -160.9 µV | 17.59 µA |
| 1 V | -142.5 µV | 19.11 µA |
| 1.2 V | -523.1 µV | 19.54 µA |
| 1.278 V | -3.125 mV | 19.66 µA |
| 1.4 V | -29.69 mV | 19.76 µA |
| 1.6 V | -153 mV | 19.79 µA |
Measured on ngspice 42, tt, 27 °C.
DC says 0.6 V is fine; speed says it is not, because slew and bandwidth both need tail current. So the references move to VL = 0.8 V and VH = 1.2 V. One LSB becomes 6.25 mV and ½ LSB 3.125 mV.
Big steps slew, small steps settle
A big step drives the input pair fully to one side. The output then moves at a fixed slew rate set by currents, not by the loop (E5.6 Slew rate and output swing). Version 0, E6.4's OPA-B, falls at 11.2 V/µs: M7's 40.6 µA minus the 19.5 µA the first stage pushes through Cc, over 2 pF, gives 10.5 V/µs. It also undershoots by 116 mV before the loop takes control again.
- version 0
- version 1
- v(dac)
- Time 370 nsversion 0 = 2.127 mV · version 1 = -170.1 µV · v(dac) = 800.1 mV
70 ns after the fall. Version 1 entered the band for good 30.9 ns after the step; version 0 leaves it for the last time at 80.7 ns.
- Time 710 nsversion 0 = -1.962 mV · version 1 = -1.011 mV · v(dac) = 856.3 mV
The 1-code step starts 1 LSB away and is inside the band 7.5 ns (version 0) and 5.3 ns (version 1) after it.
Read the plot as a table
| Time | version 0 | version 1 | v(dac) |
|---|---|---|---|
| 0 s | -176.9 µV | -187 µV | 800 mV |
| 100 ns | -176.9 µV | -187 µV | 800 mV |
| 200 ns | -472.6 µV | -524.2 µV | 1.194 V |
| 300 ns | 1.261 mV | 1.198 mV | 1.192 V |
| 370 ns | 2.127 mV | -170.1 µV | 800.1 mV |
| 400 ns | -539.1 µV | -186.9 µV | 800 mV |
| 500 ns | -935 µV | -943.4 µV | 800.8 mV |
| 600 ns | -142.5 µV | -152.3 µV | 850 mV |
| 700 ns | -202 µV | -212.5 µV | 850.1 mV |
| 710 ns | -1.962 mV | -1.011 mV | 856.3 mV |
| 800 ns | -139.5 µV | -150.1 µV | 856.3 mV |
| 900 ns | -139.4 µV | -150.1 µV | 856.2 mV |
Measured on ngspice 42, tt, 27 °C; the curves are clipped at ±20 mV.
Version 1 doubles M6 and M7, which keeps E5.5's offset rule. Now Cc sets the limit: 19.5 µA into 1 pF is 19.5 V/µs, and the run gives 17.6 V/µs.
A small step stays linear and settles like a single pole with τ = 1/(2πfu), where fu is the loop's unity-gain frequency. Version 3 has fu = 26.4 MHz, so τ = 6.04 ns; an 8-code step (50 mV) needs ln(50/3.125) = 2.77 τ = 16.7 ns. The run takes 20.9 ns: a 60° loop is not a single pole, and its overshoot must die away too (E6.3 Phase margin and the step response).
| Version | Change | Full-scale rise | Full-scale fall | 8 codes | 1 code | Lowest after the fall |
|---|---|---|---|---|---|---|
| 0 | E6.4's OPA-B | 44.6 ns | 80.7 ns | 24.5 ns | 7.5 ns | 683.8 mV |
| 1 | M6, M7 doubled: 64/1, 32/1 | 39.5 ns | 30.9 ns | 17.5 ns | 5.3 ns | 799.8 mV |
| 2 | pair 20/2, load 16/2 | 39.8 ns | 39.4 ns | 11.9 ns | 6.7 ns | 783.6 mV |
| 3 | load 32/2, M6 128/1 | 43.0 ns | 48.3 ns | 20.9 ns | 7.2 ns | 774.6 mV |
Settling to ±½ LSB, from the run above. Each version keeps the change before it.
Offset is bought with area
Version 1 still has OTA-A's pair (10/1) and load (8/1). Twenty Monte Carlo dies give σ = 2.29 mV, so 3σ = 6.88 mV: above 1 LSB. Version 2 quadruples the pair's and the load's area (E7.5 Monte Carlo on an amplifier's offset), and version 3 widens the load again.
Read the plot as a table
| Die | v(out) − v(in) |
|---|---|
| 5 | -472 µV |
| 10 | 1.459 mV |
| 15 | 1.052 mV |
| 20 | 880.2 µV |
Seed 5, input 1.0 V: mean −0.01 mV, σ = 1.03 mV, so 3σ = 3.10 mV.
The same 20 dies of version 1
Read the plot as a table
| Die | v(out) − v(in) |
|---|---|
| 5 | -1.447 mV |
| 10 | 2.724 mV |
| 15 | 1.791 mV |
| 20 | 1.573 mV |
Seed 5: σ = 2.29 mV, from −5.55 to +2.89 mV.
Twenty dies pin σ down only to about ±16 %, so a 3σ that lands near the limit is a reason to add area, not to sign off.
The corner that bites
Version 2 settles and holds its levels at tt. At the sf corner and −40 °C it fails the DC spec at the top code. The top of an NMOS pair's input range is about VDD − VSG3 + Vth1: above it, M1 leaves saturation. SKY130's sf corner pairs a slow PMOS, which raises VSG3, with a fast NMOS, which lowers Vth1 (E2.7 Corners and temperature). The cold raises VSG3 further.
- version 2
- version 3
Read the plot as a table
| Input | version 2 | version 3 |
|---|---|---|
| 700 mV | -149.8 µV | -88.19 µV |
| 800 mV | 13.66 µV | 37.73 µV |
| 900 mV | 48.87 µV | 64.35 µV |
| 1 V | 93.74 µV | 89.88 µV |
| 1.1 V | 630.6 µV | 211.5 µV |
| 1.2 V | 10.28 mV | 2.951 mV |
| 1.3 V | 47.59 mV | 33.11 mV |
At code 63: 9.02 mV for version 2, 2.42 mV for version 3. Measured on ngspice 42.
Version 3 doubles the load's width to lower VSG3, and doubles M6 with it to keep the offset rule (W/L)6/(W/L)4 = 2(W/L)7/(W/L)5. The sign-off then runs every corner at three temperatures.
| Corner | °C | Slowest settling | Step | Worst DC error (codes 0, 8, 9, 63) | Phase margin |
|---|---|---|---|---|---|
| tt | −40 | 43.2 ns | full-scale fall | 0.37 mV | 60.4° |
| tt | 27 | 48.3 ns | full-scale fall | 0.22 mV | 60.4° |
| tt | 125 | 58.7 ns | full-scale fall | 0.14 mV | 59.6° |
| ss | −40 | 43.4 ns | full-scale fall | 0.29 mV | 60.6° |
| ss | 27 | 48.1 ns | full-scale fall | 0.17 mV | 60.5° |
| ss | 125 | 58.9 ns | full-scale fall | 0.11 mV | 59.8° |
| ff | −40 | 43.1 ns | full-scale fall | 0.46 mV | 60.2° |
| ff | 27 | 48.4 ns | full-scale fall | 0.26 mV | 60.2° |
| ff | 125 | 58.5 ns | full-scale fall | 0.17 mV | 59.5° |
| sf | −40 | 43.5 ns | full-scale fall | 2.42 mV | 59.7° |
| sf | 27 | 49.0 ns | full-scale fall | 0.61 mV | 59.9° |
| sf | 125 | 59.1 ns | full-scale fall | 0.19 mV | 59.2° |
| fs | −40 | 43.3 ns | full-scale fall | 0.18 mV | 61.1° |
| fs | 27 | 42.4 ns | full-scale rise | 0.15 mV | 60.9° |
| fs | 125 | 58.2 ns | full-scale fall | 0.13 mV | 60.0° |
Spec: 70 ns, 3.125 mV, 55°. Worst cases: 59.1 ns, 2.42 mV, 59.2°. Supply current at tt: 119.3 µA.
Read the plot as a table
| Time | v(out) − v(dac) |
|---|---|
| 0 s | 50.28 µV |
| 100 ns | 50.28 µV |
| 200 ns | 215.5 µV |
| 300 ns | 789.4 µV |
| 400 ns | 51.91 µV |
| 500 ns | -209 µV |
| 600 ns | 69.87 µV |
| 700 ns | 49.4 µV |
| 800 ns | 71.4 µV |
| 900 ns | 71.4 µV |
Measured on ngspice 42 at tt; the same run also covers the other two temperatures.
The runs behind the other four corners (125 °C shown)
Read the plot as a table
| Time | v(out) − v(dac) |
|---|---|
| 0 s | 30.5 µV |
| 100 ns | 30.5 µV |
| 200 ns | 91.1 µV |
| 300 ns | 683 µV |
| 400 ns | 63.28 µV |
| 500 ns | -219.1 µV |
| 600 ns | 50.59 µV |
| 700 ns | 31.12 µV |
| 800 ns | 51.93 µV |
| 900 ns | 51.87 µV |
Measured on ngspice 42 at ss; the same run also covers the other two temperatures.
Read the plot as a table
| Time | v(out) − v(dac) |
|---|---|
| 0 s | 80.59 µV |
| 100 ns | 80.59 µV |
| 200 ns | 155.3 µV |
| 300 ns | 741.1 µV |
| 400 ns | 110.4 µV |
| 500 ns | -167.6 µV |
| 600 ns | 94.09 µV |
| 700 ns | 74.57 µV |
| 800 ns | 94.84 µV |
| 900 ns | 94.77 µV |
Measured on ngspice 42 at ff; the same run also covers the other two temperatures.
Read the plot as a table
| Time | v(out) − v(dac) |
|---|---|
| 0 s | 54.89 µV |
| 100 ns | 54.89 µV |
| 200 ns | 163.4 µV |
| 300 ns | 748.5 µV |
| 400 ns | 87.83 µV |
| 500 ns | -196 µV |
| 600 ns | 67.08 µV |
| 700 ns | 47.31 µV |
| 800 ns | 67.69 µV |
| 900 ns | 67.6 µV |
Measured on ngspice 42 at sf; the same run also covers the other two temperatures.
Read the plot as a table
| Time | v(out) − v(dac) |
|---|---|
| 0 s | 53.42 µV |
| 100 ns | 53.42 µV |
| 200 ns | 115.9 µV |
| 300 ns | 703.3 µV |
| 400 ns | 83.67 µV |
| 500 ns | -193.4 µV |
| 600 ns | 76.52 µV |
| 700 ns | 57.3 µV |
| 800 ns | 78.14 µV |
| 900 ns | 78.08 µV |
Measured on ngspice 42 at fs; the same run also covers the other two temperatures.
Break it
Now swap roles. Four faulty copies of the final design are built, each a realistic mistake. Your job is a bench whose lines pass the good design and fail every copy. A passing simulation proves the bench, not the block, unless the bench can fail.
- Dynamic faults
No Rz and a starved bias leave the settled DC levels right, so only the settling lines catch them for sure.
Read the diagram as text
- Your bench: stimulus and meas lines
- Final design
- No Rz: phase margin
- Bias 5 µA: slew rate
- Load mirror 4/2: input range
- M2 22/2: offset
- Verdicts: pass, fail × 4
- Your bench → Final design
- Your bench → No Rz
- Your bench → Bias 5 µA
- Your bench → Load mirror 4/2
- Your bench → M2 22/2
- Final design → Verdicts
- No Rz → Verdicts
- Bias 5 µA → Verdicts
- Load mirror 4/2 → Verdicts
- M2 22/2 → Verdicts
| Copy | Worst DC error | Fall settles | 1-code overshoot | Caught by |
|---|---|---|---|---|
| final design | 0.22 mV | 48.3 ns | 0.69 mV | passes every line |
| Rz removed | 0.24 mV | 112.3 ns | 2.55 mV | settling |
| bias 5 µA | 6.83 mV | 176.1 ns | 1.01 mV | settling (DC at code 63 is read before it settles) |
| load mirror 4/2 | 551.31 mV | 86.5 ns | 0.00 mV | DC at the upper codes, settling |
| M2 drawn 22/2 | 5.53 mV | 48.7 ns | 0.74 mV | DC at every code |
From one run of the five copies at tt, 27 °C (codes 0, 63, 0, 32, 33; each DC error read 1 ns before the next code). Limits: 3.125 mV and 70 ns.
- final design
- no R_z
- bias 5 µA
- Time 370 nsfinal design = 61.54 µV · no R_z = 17.13 mV · bias 5 µA = 164.3 mV
70 ns after the fall only the final design has settled for good. Without Rz the output rings until 112.3 ns; the starved copy slews until 176.1 ns.
Read the plot as a table
| Time | final design | no R_z | bias 5 µA |
|---|---|---|---|
| 0 s | 50.28 µV | 50.28 µV | 93.29 µV |
| 100 ns | 50.28 µV | 50.28 µV | 93.29 µV |
| 200 ns | 215.5 µV | -3.915 mV | -29.01 mV |
| 300 ns | 789.4 µV | 819.1 µV | -6.087 mV |
| 370 ns | 61.54 µV | 17.13 mV | 164.3 mV |
| 400 ns | 51.91 µV | 2.84 mV | 34.21 mV |
| 500 ns | -1.362 mV | -1.29 mV | 5.276 mV |
| 600 ns | 96.08 µV | -1.484 mV | 22.49 mV |
| 700 ns | 75.11 µV | 110.3 µV | 902.4 µV |
| 800 ns | 96.97 µV | 155.3 µV | 108.6 µV |
| 900 ns | 96.97 µV | 96.41 µV | 129.2 µV |
Measured on ngspice 42; clipped at ±20 mV.
What the digital side sees
The sign-off table is the spec a behavioural buffer model must meet: settle within 59.1 ns, a DC error within 2.42 mV, an offset of σ = 1.03 mV. A model that is an ideal wire passes every digital check and every fault above.
Asked in interviews
How do you specify and verify settling time?
State the step sizes, the error band (often ½ LSB) and the time after the step. Measure the last time the output leaves the band, for the largest and smallest steps, at every corner and temperature.
What limits settling for large and small steps?
A large step saturates the input pair, so currents set the slew rate: tail current into Cc, or the output stage into the load. A small step stays linear and settles with τ = 1/(2πfu); low phase margin adds ringing.
How would you verify an analog block in a mixed-signal regression?
Write checks that fail on known faulty versions first: static levels, settling, overshoot, corners. Then compare the behavioural model against the circuit on the same bench.
Try it
Run the netlist. The err_* lines are DC errors at four codes, the ts_* lines the end of each step's settling, and over_s1 the 1-code overshoot. Every line must stay inside 3.125 mV or 70 ns after its step.
Break it: add rz=1 to the end of the X1 line and predict which lines fail before you run. Then try ib=5u, wl=4 and dw2=2 one at a time. Last, the design route: replace the sizes with version 1's w6=64 w7=32 and see which lines move.
Run the netlist to draw its plots here.
err_c0 = 5.028494e-05 err_c63 = 2.173663e-04 err_c32 = 9.584489e-05 err_c33 = 9.696778e-05Check yourself
Remember
- Choose the DAC references inside the buffer's input range at speed: the tail must stay saturated, not only the DC error small.
- Big steps are slew-limited (tail current into Cc, or the output stage into the load); small steps settle linearly with τ = 1/(2πfu).
- Offset is bought with area, and a corner sweep can move an edge of the input range past the top code.
- A bench is only trusted once it fails known faults: DC-level checks never see a missing Rz or a starved bias.