SLiCAP DC and dcvar analysis
SLiCAP dc variance analysis doDCvar() is intended to set up design equations for offset and bias voltages and currents, and for resistor tolerances. Similar as with noise analysis, SLiCAP can determine the detector-referred and the source-referred variance of a DC voltage or current. To this end, independent sources are assigned a mean DC value and an absolute variance, while resistors can be assigned a relative variance. Resistor temperature tracking and tolerance matching is achieved by assigning resistors to a lot.
SLiCAP output displayed on this manual page, is generated with the script: dcvar.py
, imported by Manual.py
.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4dcvar.py: SLiCAP scripts for the HTML help file
5"""
6import SLiCAP as sl
7import sympy as sp
dc and dcvar parameters
A doDCvar() analysis is always preceeded by a doDC() analysis. The DC analysis results are used to convert resistor tolerances into resistor error currents.
SLiCAP uses the dc
parameter of independent sources during doDC() analysis and the dcvar
, and dcvarlot
parameters during doDCvar() analysis.
Voltage source DC variance
The dcvar
parameter of independent voltage sources must be specified in \(\mathrm{V^2}\). The variance is the square of the standard deviation.
The netlist syntax of a voltage source V1
connected between nodeP
and nodeN
with a mean (DC) value of 1 V and a standard deviation of 10 mV is:
V1 nodeP nodeN V value=0 dc=1 dcvar=1e-4 noise=0
Current source DC variance
The dcvar
parameter of independent current sources must be specified in \(\mathrm{A^2}\)
The netlist syntax of a current source I1
flowing from nodeP
to nodeN
with a mean (DC) value of 1 mA and a standard deviation of 1 uA is:
I1 nodeP nodeN V value=0 dc=1e-3 dcvar=1e-12 noise=0
Resistor tolerance and matching tolerance
SLiCAP models resistor tolerances by placing independent error current sources in parallel with the resistor. To this end, it first evaluates the DC current through the resistor and places an independent current source in parallel with this resistor. The dcvar
parameter of this current source is set to the product of the squared DC resistor current and the relative variance of its resistance.
dcvar analysis
SLiCAP adds dc error current sources in parallel with resistors that have a nonzero dcvar
parameter. These current sources obtain the reference designator I_dcvar_<resID>
, where resID
is the reference designator of the resistor. After dcvar analysis, all independent current sources with reference designators starting with I_dcvar_
will be removed from the circuit.
If the resistor tolerance partly matches with that of resistors belonging to the same lot, the matching error current is derived from a voltage source of which dcvar
describes the matching part of the variance. The dcvar
parameters of the individual resistors model the mismatch.
lot specification
For each dcvarlot
specification, SLiCAP adds a grounded independent voltage source that has a nonzero dcvar
parameter. These voltage sources obtain the reference designator V_dcvar_<dcvarlot_xx>
, where dcvarlot_xx
is the value of the dcvarlot
parameter. A voltage-controlled current source with reference designator G_dcvar_<resID>
converts the voltage from this voltage source into an error current in parallel with the resistor. The gain of this conversion equals the DC current through the resistor. After dcvar analysis, all independent voltage sources sources with reference designators starting with V_dcvar_
, and all voltage-controlled current sources starting with reference designator G_dcvar_
with will be removed from the circuit.
Modeling of temperature dependency
Both the mean value (dc
) and the variance (dcvar
) of voltage sources, current sources and resistors can be made temperature dependent.
Below the syntax of a resistor R1
connected between nodeP
and nodeN
, with a temperature coefficient \(\mathrm{TC}\), a relative tolerance (1-\(\sigma\) value) of 0.5% and a temperature coefficient tolerance of 2%.
R1 nodeP nodeN R value={1+TC*(T-T_0)} dcvar={0.5^2 + TC*(T-T_0)*0.02^2} noisetemp=0 noiseflow=0
Temperature tracking is modeled by using similar temperature dependency expressions for tracking devices.
Subcircuits with dcvar
Built-in subcircuits
Below an overview of subcircuits and symbols for dcvar analysis. Subcircuits are defined in the library SLiCAP.lib
in the folder indicated by ini.main_lib_path
.
subcircuit name |
description |
parameters |
KiCAD |
gschem/Lepton-EDA |
LTspice |
---|---|---|---|---|---|
N_dcvar |
Nullor with equivalent-input bias and offset |
sib, sio, svo, iib |
N_dcvar |
N_dcvar |
SLN_dcvar |
O_dcvar |
Nullor with equivalent-input bias and offset |
sib, sio, svo, iib |
O_dcvar |
O_dcvar |
SLO_dcvar |
Wide table: slide below the table!
Create dcvar elements
The user can create circuits for dcvar analysis using independent dcvar sources, resistors and predefined dcvar subcircuits from above.
DC variance analysis
At the beginning of a doDCvar(), SLiCAP performs a doDC() analysis and adds resistor error current sources to the circuit (see above).
Important
The function doDCvar() sets the attributes dcSolve
, ovar
, svarTerms
, and ovarTerms
of the returned instruction object. The attributes ivar
and ivarTerms
are only set if the circuit has a source specification.
9# Define the circuit
10cir = sl.makeCircuit("kicad/dcMatchingTracking/dcMatchingTracking.kicad_sch")
11# Perform dc variance analysis
12dcvarResult = sl.doDCvar(cir, source="V1", detector="V_out", pardefs="circuit")
DC solution
14dcSolve = dcvarResult.dcSolve
15Iv, M, Dv = dcvarResult.Iv, dcvarResult.M, dcvarResult.Dv
16print(dcvarResult.Dv, "=", dcSolve)
This yields:
Matrix([[-V_DC_T/(R_a + R_b)], [V_DC_T], [R_b*V_DC_T/(R_a + R_b)]])
Typesetted:
Important
doDCvar()
returns the matrix equation of the DC solution. Hence, dcvar sources of resistors are not shown.
Detector-referred DC variance
15ovar = dcvarResult.ovar
16print(ovar)
This yields:
2*R_a**2*R_b**2*V_DC_T**2*var_m/(R_a + R_b)**4 + R_b**2*V_DC_T**2*sigma_V**2/(R_a + R_b)**2
Typesetted:
Source-referred DC variance
21ivar = dcvarResult.ivar
22print(ivar)
This yields:
2*R_a**2*V_DC_T**2*var_m/(R_a + R_b)**2 + V_DC_T**2*sigma_V**2
Typesetted:
Contributions to detector-referred and source-referred DC variance
24svarTerms = dcvarResult.svarTerms
25ovarTerms = dcvarResult.ovarTerms
26ivarTerms = dcvarResult.ivarTerms
27for term in svarTerms:
28 print("\n= " + term + " =")
29 print("value :", svarTerms[term])
30 print("det-referred :", ovarTerms[term])
31 print("src-referred :", ivarTerms[term])
This yields:
= V1 =
value : V_DC_T**2*sigma_V**2
det-referred : R_b**2*V_DC_T**2*sigma_V**2/(R_a + R_b)**2
src-referred : V_DC_T**2*sigma_V**2
= I_dcvar_R1 =
value : V_DC_T**2*var_m/(R_a + R_b)**2
det-referred : R_a**2*R_b**2*V_DC_T**2*var_m/(R_a + R_b)**4
src-referred : R_a**2*V_DC_T**2*var_m/(R_a + R_b)**2
= V_dcvar_lot_1 =
value : T_Delta**2*sigma_TC_R**2 + sigma_R**2
det-referred : 0
src-referred : 0
= I_dcvar_R2 =
value : V_DC_T**2*var_m/(R_a + R_b)**2
det-referred : R_a**2*R_b**2*V_DC_T**2*var_m/(R_a + R_b)**4
src-referred : R_a**2*V_DC_T**2*var_m/(R_a + R_b)**2
Typesetted:
Value |
Units |
|
---|---|---|
V1: Source value |
\(V_{DC}^{2} \sigma_{V}^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2}\) |
\(\mathrm{V^2}\) |
V1: Source-referred |
\(V_{DC}^{2} \sigma_{V}^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2}\) |
\(\mathrm{V^2}\) |
V1: Detector-referred |
\(\frac{V_{DC}^{2} \sigma_{V}^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2}}{A^{2}}\) |
\(\mathrm{V^2}\) |
I_dcvar_R1: Source value |
\(\frac{V_{DC}^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2} \left(0.5 T_{\Delta}^{2} \sigma_{TC tr R}^{2} + 0.5 \sigma_{m R}^{2}\right)}{A^{2} R^{2} \left(TC_{R} T_{\Delta} + 1\right)^{2}}\) |
\(\mathrm{A^2}\) |
I_dcvar_R1: Source-referred |
\(\frac{0.5 V_{DC}^{2} \left(A - 1\right)^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2} \left(T_{\Delta}^{2} \sigma_{TC tr R}^{2} + \sigma_{m R}^{2}\right)}{A^{2}}\) |
\(\mathrm{V^2}\) |
I_dcvar_R1: Detector-referred |
\(\frac{0.5 V_{DC}^{2} \left(A - 1\right)^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2} \left(T_{\Delta}^{2} \sigma_{TC tr R}^{2} + \sigma_{m R}^{2}\right)}{A^{4}}\) |
\(\mathrm{V^2}\) |
V_dcvar_lot_1: Source value |
\(T_{\Delta}^{2} \sigma_{TC R}^{2} + \sigma_{R}^{2}\) |
\(\mathrm{V^2}\) |
V_dcvar_lot_1: Source-referred |
\(0\) |
\(\mathrm{V^2}\) |
V_dcvar_lot_1: Detector-referred |
\(0\) |
\(\mathrm{V^2}\) |
I_dcvar_R2: Source value |
\(\frac{V_{DC}^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2} \left(0.5 T_{\Delta}^{2} \sigma_{TC tr R}^{2} + 0.5 \sigma_{m R}^{2}\right)}{A^{2} R^{2} \left(TC_{R} T_{\Delta} + 1\right)^{2}}\) |
\(\mathrm{A^2}\) |
I_dcvar_R2: Source-referred |
\(\frac{0.5 V_{DC}^{2} \left(A - 1\right)^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2} \left(T_{\Delta}^{2} \sigma_{TC tr R}^{2} + \sigma_{m R}^{2}\right)}{A^{2}}\) |
\(\mathrm{V^2}\) |
I_dcvar_R2: Detector-referred |
\(\frac{0.5 V_{DC}^{2} \left(A - 1\right)^{2} \left(TC_{V} T_{\Delta} + 1\right)^{2} \left(T_{\Delta}^{2} \sigma_{TC tr R}^{2} + \sigma_{m R}^{2}\right)}{A^{4}}\) |
\(\mathrm{V^2}\) |
Tolerances, temperature drift, matching and tracking
11# Perform dc variance analysis
12dcvarResult = sl.doDCvar(cir, source="V1", detector="V_out", pardefs="circuit")
13
14dcSolve = dcvarResult.dcSolve
15Iv, M, Dv = dcvarResult.Iv, dcvarResult.M, dcvarResult.Dv
16print(dcvarResult.Dv, "=", dcSolve)
17
18ovar = dcvarResult.ovar
19print(ovar)
20
21ivar = dcvarResult.ivar
22print(ivar)
23
24svarTerms = dcvarResult.svarTerms
25ovarTerms = dcvarResult.ovarTerms
26ivarTerms = dcvarResult.ivarTerms
No tolerances and no temperature coefficients
49###############################################################################
50# No tolerances and no temperature coefficients
51###############################################################################
52dcVarResult_1a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
53dcSolve_1 = dcVarResult_1a.dcSolve
54idx_v = cir.depVars().index('V_out')
55Vout_1 = sp.simplify(dcSolve_1[idx_v])
56dcVarResult_1b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
57idx_i = cir.depVars().index('I_V1')
58IV1_1 = sp.simplify(dcVarResult_1b.dcSolve[idx_i])
59I_ovar_1 = sp.simplify(dcVarResult_1b.ovar)
60print("\nCase 1")
61print("V_out :", Vout_1)
62print("I(V1) :", IV1_1)
63print("var{I(V1)}:", I_ovar_1)
This yields:
V_out : V_DC/A
I(V1) : -V_DC/(A*R)
var{I(V1)}: 0
Typesetted:
DC voltage soure with standard deviation
65###############################################################################
66# Only DC voltage soure with standard deviation
67###############################################################################
68cir.delPar("sigma_V")
69
70dcVarResult_2a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
71dcSolve_2 = dcVarResult_2a.dcSolve
72Vout_2 = sp.simplify(dcSolve_2[idx_v])
73dcVarResult_2b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
74IV1_2 = sp.simplify(dcVarResult_2b.dcSolve[idx_i])
75I_ovar_2 = sp.simplify(dcVarResult_2b.ovar)
76print("\nCase 2")
77print("V_out :", Vout_2)
78print("I(V1) :", IV1_2)
79print("var{I(V1)}:", I_ovar_2)
This yields:
Case 2
V_out : V_DC/A
I(V1) : -V_DC/(A*R)
var{I(V1)}: V_DC**2*sigma_V**2/(A**2*R**2)
Typesetted:
DC voltage soure with temperature coefficient
81###############################################################################
82# Only DC voltage soure with temperature coefficient
83###############################################################################
84cir.defPar("sigma_V", 0)
85cir.delPar("TC_V")
86
87dcVarResult_3a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
88dcSolve_3 = dcVarResult_3a.dcSolve
89Vout_3 = sp.simplify(dcSolve_3[idx_v])
90dcVarResult_3b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
91IV1_3 = sp.simplify(dcVarResult_3b.dcSolve[idx_i])
92I_ovar_3 = sp.simplify(dcVarResult_3b.ovar)
93print("\nCase 3")
94print("V_out :", Vout_3)
95print("I(V1) :", IV1_3)
96print("var{I(V1)}:", I_ovar_3)
This yields:
Case 3
V_out : V_DC*(TC_V*T_Delta + 1)/A
I(V1) : -V_DC*(TC_V*T_Delta + 1)/(A*R)
var{I(V1)}: 0
Typesetted:
DC voltage soure with stddev. and tempco.
98###############################################################################
99# Only DC voltage soure with standard deviation and temperature coefficient
100###############################################################################
101cir.delPar("sigma_V")
102
103dcVarResult_4a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
104dcSolve_4 = dcVarResult_4a.dcSolve
105Vout_4 = sp.simplify(dcSolve_4[idx_v])
106dcVarResult_4b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
107IV1_4 = sp.simplify(dcVarResult_4b.dcSolve[idx_i])
108I_ovar_4 = sp.simplify(dcVarResult_4b.ovar)
109print("\nCase 4")
110print("V_out :", Vout_4)
111print("I(V1) :", IV1_4)
112print("var{I(V1)}:", I_ovar_4)
This yields:
Case 4
V_out : V_DC*(TC_V*T_Delta + 1)/A
I(V1) : -V_DC*(TC_V*T_Delta + 1)/(A*R)
var{I(V1)}: V_DC**2*sigma_V**2*(TC_V*T_Delta + 1)**2/(A**2*R**2)
Typesetted:
Rel. stddev of resistor values, perfect matching
114###############################################################################
115# Only (relative) standard deviation of resistor values with perfect matching
116###############################################################################
117cir.defPar("sigma_V", 0) # Standard deviation of voltage source [V]
118cir.defPar("TC_V", 0) # Rel.temperature coefficient of voltage source [1/K]
119cir.delPar("sigma_R")
120
121dcVarResult_5a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
122dcSolve_5 = dcVarResult_5a.dcSolve
123Vout_5 = sp.simplify(dcSolve_5[idx_v])
124dcVarResult_5b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
125IV1_5 = sp.simplify(dcVarResult_5b.dcSolve[idx_i])
126I_ovar_5 = sp.simplify(dcVarResult_5b.ovar)
127print("\nCase 5")
128print("V_out :", Vout_5)
129print("I(V1) :", IV1_5)
130print("var{I(V1)}:", I_ovar_5)
This yields:
Case 5
V_out : V_DC/A
I(V1) : -V_DC/(A*R)
var{I(V1)}: V_DC**2*sigma_R**2/(A**2*R**2)
Typesetted:
Rel. stddev of resistor values, perfect matching and tracking
132###############################################################################
133# Only (relative) standard deviation of resistor values with perfect matching
134# and temperature tracking
135###############################################################################
136cir.delPar("TC_R")
137
138dcVarResult_6a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
139dcSolve_6 = dcVarResult_6a.dcSolve
140Vout_6 = sp.simplify(dcSolve_6[idx_v])
141dcVarResult_6b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
142IV1_6 = sp.simplify(dcVarResult_6b.dcSolve[idx_i])
143I_ovar_6 = sp.simplify(dcVarResult_6b.ovar)
144print("\nCase 6")
145print("V_out :", Vout_6)
146print("I(V1) :", IV1_6)
147print("var{I(V1)}:", I_ovar_6)
This yields:
Case 6
V_out : V_DC/A
I(V1) : -V_DC/(A*R*(TC_R*T_Delta + 1))
var{I(V1)}: V_DC**2*sigma_R**2/(A**2*R**2*(TC_R*T_Delta + 1)**2)
Typesetted:
Rel. stddev of resistor values, imperfect matching and tracking
149###############################################################################
150# Only (relative) standard deviation of resistor values with imperfect
151# matching and temperature tracking
152###############################################################################
153cir.delPar("sigma_m_R")
154cir.delPar("sigma_TC_R")
155cir.delPar("sigma_TC_tr_R")
156
157dcVarResult_7a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
158dcSolve_7 = dcVarResult_6a.dcSolve
159Vout_7 = sp.simplify(dcSolve_7[idx_v])
160dcVarResult_7b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
161IV1_7 = sp.simplify(dcVarResult_7b.dcSolve[idx_i])
162I_ovar_7 = sp.simplify(dcVarResult_7b.ovar)
163print("\nCase 7")
164print("V_out :", Vout_7)
165print("I(V1) :", IV1_7)
166print("var{I(V1)}:", I_ovar_7)
This yields:
Case 7
V_out : V_DC/A
I(V1) : -V_DC/(A*R*(TC_R*T_Delta + 1))
var{I(V1)}: V_DC**2*(2*A**2*(T_Delta**2*sigma_TC_R**2 + sigma_R**2) + (T_Delta**2*sigma_TC_tr_R**2 + sigma_m_R**2)*((A - 1)**2 + 1))/(2*A**4*R**2*(TC_R*T_Delta + 1)**2)
Typesetted:
V src stddev and tempco, rel. res. stddev. imperf. matching/tracking
168###############################################################################
169# DC voltage soure with standard deviation and temperature coefficient and
170# (relative) standard deviation of resistor values with imperfect matching
171# and temperature tracking
172###############################################################################
173cir.delPar("TC_V")
174cir.delPar("sigma_V")
175cir.delPar("sigma_TC_V")
176
177dcVarResult_8a = sl.doDCvar(cir, detector="V_out", pardefs="circuit")
178dcSolve_8 = dcVarResult_8a.dcSolve
179Vout_8 = sp.simplify(dcSolve_8[idx_v])
180dcVarResult_8b = sl.doDCvar(cir, detector="I_V1", pardefs="circuit")
181IV1_8 = sp.simplify(dcVarResult_8b.dcSolve[idx_i])
182I_ovar_8 = sp.simplify(dcVarResult_8b.ovar)
183print("\nCase 8")
184print("V_out :", Vout_8)
185print("I(V1) :", IV1_8)
186print("var{I(V1)}:", I_ovar_8)
This yields:
Case 8
V_out : V_DC*(TC_V*T_Delta + 1)/A
I(V1) : -V_DC*(TC_V*T_Delta + 1)/(A*R*(TC_R*T_Delta + 1))
var{I(V1)}: V_DC**2*(2*A**2*(T_Delta**2*sigma_TC_R**2 + sigma_R**2 + sigma_V**2) + (T_Delta**2*sigma_TC_tr_R**2 + sigma_m_R**2)*((A - 1)**2 + 1))*(TC_V*T_Delta + 1)**2/(2*A**4*R**2*(TC_R*T_Delta + 1)**2)
Typesetted:
Display equations on HTML pages and in LaTeX documents
The report module Create reports, discusses how HTML snippets and LaTeX snippets can be created for variables, expressions, equations and tables.
As a matter of fact, all equations, tables and figures on this page are created with this module:
188# Create an RST formatter
189rst = sl.RSTformatter()
190# Save expressions in the sphinx/SLiCAPdata folder of the project directory
191rst.eqn(dcvarResult.Dv, dcSolve).save("eqn-dcSolve")
192rst.matrixEqn(Iv, M, Dv).save("eqn-dcMatrix")
193rst.eqn("(sigma_o)^2", ovar, units="V**2").save("eqn-ovar")
194rst.eqn("(sigma_i)^2", ivar, units="V**2").save("eqn-ivar")
195rst.dcvarContribs(dcvarResult, "DC variance contributions").save("table-varContribs")
196rst.eqn("(sigma_I_V1)^2", I_ovar_1, units="A**2").save("eqn-I_ovar_1")
197rst.eqn("(sigma_I_V1)^2", I_ovar_2, units="A**2").save("eqn-I_ovar_2")
198rst.eqn("(sigma_I_V1)^2", I_ovar_3, units="A**2").save("eqn-I_ovar_3")
199rst.eqn("(sigma_I_V1)^2", I_ovar_4, units="A**2").save("eqn-I_ovar_4")
200rst.eqn("(sigma_I_V1)^2", I_ovar_5, units="A**2").save("eqn-I_ovar_5")
201rst.eqn("(sigma_I_V1)^2", I_ovar_6, units="A**2").save("eqn-I_ovar_6")
202rst.eqn("(sigma_I_V1)^2", I_ovar_7, units="A**2").save("eqn-I_ovar_7")
203rst.eqn("(sigma_I_V1)^2", I_ovar_8, units="A**2").save("eqn-I_ovar_8")
The typesetted tables and equations are shown on this page.