Measuring with .meas

Turn a simulated waveform into numbers with meas: delays, rise times, extremes and energy, with the crossing named and the result checked.

Lesson
E1.5
Time
25 min
Runs on
ngspice
Check
5 questions

A characterization script measured an RC delay with TRIG v(in) VAL=0.5 RISE=1 TARG v(out) VAL=0.5 RISE=1. Before the input edge, a glitch pushed the output past 0.5 V, so the first rise of v(out) came first. The script wrote a delay of −17.71 µs into a spreadsheet that nobody checked.

TransientThe first crossing is the glitchA 0.5 µs current glitch lifts v(out) at 2 µs. The real input edge arrives at 20 µs.
  • v(in)
  • v(out)
00.2 V0.4 V0.6 V0.8 V1.0 V1.2 VVoltage05 µs10 µs15 µs20 µs25 µs30 µsTimeVAL=0.5first rise of v(out)the crossing you meant00.2 V0.4 V0.6 V0.8 V1.0 V1.2 VVoltage010 µs20 µs30 µsTimeVAL=0.5first rise of v(out)the crossing you meant
  1. Time 2.293 µsv(in) = 0 V · v(out) = 499.3 mV

    v(out) rises through 0.5 V at 2.293 µs, on the glitch. TARG with RISE=1 stops here, before the TRIG edge, so the delay comes out negative.

  2. Time 20 µsv(in) = 396.8 mV · v(out) = 216 µV

    The input crosses 0.5 V at 20.0005 µs, halfway up its 1 ns edge. This is the TRIG point.

  3. Time 20.69 µsv(in) = 1 V · v(out) = 499.9 mV

    v(out) crosses 0.5 V again at 20.69 µs. Counting from the TRIG point, that is a delay of 693.1 ns, which is ln 2 · τ for τ = 1 µs.

Read the plot as a table
Timev(in)v(out)
0 s0 V0 V
2.293 µs0 V499.3 mV
5 µs0 V64.91 mV
10 µs0 V437.5 µV
15 µs0 V2.948 µV
20 µs297.7 mV49.62 µV
20 µs396.8 mV216 µV
20.69 µs1 V499.9 mV
25 µs1 V993.3 mV
30 µs1 V1 V

Measured on ngspice 42 (500 of the run's points).

A meas line answers exactly the question you wrote, so write the question with care.

Turning a curve into a number

meas runs after an analysis has finished. It reads the saved vectors and prints one line per result, such as tdelay = 6.931367e-07. Inside a .control block the result also becomes a vector, so a later let or meas can use it.

FormThe question it answersIn the lab
FIND v(x) AT=tWhat is v(x) at time t?every E1.3 milestone
WHEN v(x)=valWhen does v(x) cross val?the predict item below
FIND v(y) WHEN v(x)=valWhat is v(y) when v(x) crosses val?the phase at −3 dB in E1.4
TRIG ... TARG ...How long from one crossing to another?tdelay, trise
MIN MAX PP AVG RMSExtreme, peak-to-peak, mean or RMS over a windowvglitch
INTEGThe area under a curve over a windowesrc, eheat

FROM= and TO= set the window; TD= starts the search later.

The crossing forms take a count. RISE=2 means the second time the signal rises through the value, FALL=1 the first time it falls, and CROSS=3 the third crossing in either direction. LAST picks the final one. TD=20u ignores everything before 20 µs.

Most forms also print where they found their answer. vglitch = 7.843741e-01 at= 2.507000e-06 says the glitch peaked at 0.7844 V at 2.507 µs, just as the current pulse ended. A TRIG ... TARG line prints both crossing times, trig= and targ=, which is the quickest way to see which edges a delay was measured between.

A meas line cannot compute an expression of vectors inside .control. Build the vector first with let, then measure it. The lab does that for the power the source delivers, let p = -v(in)*i(V1). The minus sign undoes the SPICE convention that a delivering source has a negative current.

Name the crossing

The hook's line asked for the first rise of v(out) past 0.5 V, and the glitch supplied it. Two small changes ask the question that was meant.

The first crossing

meas tran tbad TRIG v(in) VAL=0.5 RISE=1 TARG v(out) VAL=0.5 RISE=1

tbad = -1.770781e-05: the target is the glitch at 2.293 µs, 17.71 µs before the trigger.

The crossing after the edge

meas tran tdelay TRIG v(in) VAL=0.5 RISE=1 TARG v(out) VAL=0.5 RISE=1 TD=20u

tdelay = 6.931367e-07: 693.1 ns, which is ln 2 · τ.

Both lines are in the lab netlist, measured on ngspice 42.

The rise time in the lab uses the other fix. Its trigger, TRIG v(out) VAL=0.1 RISE=2, skips the glitch's rise by counting it. The result, trise = 2.197201e-06, is the 10 % to 90 % time of E1.3, ln 9 · τ.

Prefer TD= when you know when the event starts, and a count when you know how many edges come first. Never trust "the first one" on a waveform you have not looked at.

Check that it worked, and check it on a known answer

A meas that finds no crossing prints a line ending in failed! and creates no vector. A later let that uses it stops with an error, as below, and every line after it that needs the value fails too. Read the log for failed, and never let a script reuse an old number.

v(out) never reaches 1.5 V on a 1 V step, so there is no crossing to find. Measured on ngspice 42.
meas tran t15 WHEN v(out)=1.5
let x = t15*2
* the log:
* meas tran t15 when v(out)=1.5 failed!
* Error: RHS "t15*2" invalid

A script usually turns a number into a verdict with if. Inside .control, comparisons are written gt, lt, ge and le. A condition on a vector that a failed meas never created counts as false, so the else branch runs. Write the test so that only a good number can reach PASS.

PASS unless proven bad

if tdelay lt 0.65u or tdelay gt 0.75u
  echo FAIL tdelay
else
  echo PASS tdelay
end

C1 typed as 1u: v(out) never reaches 0.5 V, tdelay fails, and the log still says PASS tdelay.

PASS only on a good number

if tdelay gt 0.65u and tdelay lt 0.75u
  echo PASS tdelay
else
  echo FAIL tdelay
end

The same broken bench prints FAIL tdelay. With C1 = 1n both print PASS tdelay.

Both follow the lab's tdelay line on the bench without the glitch, measured on ngspice 42.

Then test the measurement on a circuit whose answer you know. Charging a capacitor C to V through any resistor takes energy C·V2 from the source. Half is stored in the capacitor, and the other half is burned in the resistor, whatever its value.

TransientPower from the source while C chargesThe lab's RC from 0 to 30 µs: v(out) above, the power the source delivers below. The area under the power curve is the energy.
  • v(out)
  • p = −v(in)·i(V1)
00.2 V0.4 V0.6 V0.8 V1.0 V1.2 VVoltage00.2 mW0.4 mW0.6 mW0.8 mW1.0 mW1.2 mWSource power05 µs10 µs15 µs20 µs25 µs30 µsTimeINTEG FROM=20u00.5 V1.0 V1.5 VVoltage00.5 mW1.0 mW1.5 mWSource power010 µs20 µs30 µsTimeINTEG FROM=20u
  1. Time 20 µsv(out) = 631 µV · p = −v(in)·i(V1) = 530 µW

    Right after the edge the full 1 V sits across R1: the source delivers 1 mW.

  2. Time 20.69 µsv(out) = 499.9 mV · p = −v(in)·i(V1) = 500.1 µW

    At the 50 % point the current has halved, and so has the power.

  3. Time 25 µsv(out) = 993.3 mV · p = −v(in)·i(V1) = 6.743 µW

    Five time constants later the power is almost zero. The area under the whole pulse, esrc, is 0.9998 nJ.

Read the plot as a table
Timev(out)p = −v(in)·i(V1)
0 s0 V0 W
5 µs64.91 mV0 W
10 µs437.5 µV0 W
15 µs2.948 µV0 W
20 µs49.62 µV89.28 µW
20 µs631 µV530 µW
20.69 µs499.9 mV500.1 µW
25 µs993.3 mV6.743 µW
30 µs1 V45.42 nW

Measured on ngspice 42 (500 of the run's points).

The lab measures esrc = 9.99837e-10 from the source and eheat = 4.99841e-10 in R1: C·V2 = 1 nJ and half of it, to 0.02 %. Without the glitch source I2, change R1 to 2 kΩ: the charge takes twice as long, and esrc still reads 0.9999 nJ. The small shortfall is the 1 ns input edge: a ramp charges a little more gently than a step.

Asked in interviews
  1. How do you measure propagation delay and rise time in SPICE?

    With TRIG/TARG: delay from the input's 50 % crossing to the output's, rise time from the output's 10 % to its 90 % crossing. Name the edge with RISE/FALL counts or TD, and check the result is positive and plausible.

  2. How do you measure the average power of a block?

    Build the supply power with let, p = −v(vdd)·i(VDD), then use AVG over a whole number of periods, or INTEG for energy per event. Exclude the start-up transient from the window.

  3. What do you do when a .meas fails?

    Read why: usually the crossing never happens in the window, or a count is too high. Plot the signal, fix the value, window or count, and make the script stop on "failed" rather than reuse an old result.

Try it

Run it and read the seven lines. tbad is negative, tdelay and trise match the RC milestones of E1.3, vglitch shows how high the glitch went, and e5 shows what a short window misses.

Now delete the I2 line and rerun. tbad turns into the same number as tdelay, and trise fails: with no glitch there is no second rise. Change its count to RISE=1. Then change R1 to 2k and predict tdelay, esrc and eheat before you run.

SPICEngspice 42 · simulator service
Edit the netlist, then run it
Expected measurements: tbad = -1.770781e-05 targ= 2.292689e-06 trig= 2.000050e-05 tdelay = 6.931367e-07 targ= 2.069364e-05 trig= 2.000050e-05 trise = 2.197201e-06 targ= 2.230306e-05 trig= 2.010586e-05 vglitch = 7.843741e-01 at= 2.507000e-06 esrc = 9.99837e-10 from= 2.00000e-05 to= 7.00000e-05 eheat = 4.99841e-10 from= 2.00000e-05 to= 7.00000e-05 e5 = 9.93096e-10 from= 2.00000e-05 to= 2.50000e-05

Check yourself

Predict the outputThe source starts after 10 µs, has 2 ns edges, and repeats every 50 µs. Type the line meas prints (for example t2 = 2.000050e-05).
* count the edges
V1 in 0 PULSE(0 1 10u 2n 2n 20u 50u)
R1 in 0 1k
.control
tran 10n 100u
meas tran t2 WHEN v(in)=0.5 RISE=2
.endc
.end
ConceptIn a .control block, meas tran t15 WHEN v(out)=1.5 finds no crossing. The next two lines are let x = t15*2 and meas tran vmx MAX v(out). What does the log show after the failure?
ConceptWhich line still measures the glitch on the lab bench, instead of the RC delay after the edge?
ConceptWhy does the energy the source delivers to charge C to V not depend on R?
ConceptOn the glitch plot, when does v(out) first rise through 0.5 V?

Remember

  • meas turns saved vectors into numbers after the run: FIND AT, WHEN, FIND WHEN, TRIG/TARG, MIN/MAX/PP/AVG/RMS and INTEG over a FROM/TO window.
  • Name the crossing with RISE, FALL or CROSS counts, or start the search later with TD; never trust the first crossing on an unseen waveform.
  • A failed meas prints "failed!" and creates no vector; anything that uses it fails, so stop on it instead of reusing an old value.
  • Inside .control, build expressions with let and measure the new vector.
  • Check a bench on a known answer: charging C to V costs C·V2 from the source, half of it heat in R, for any R.