Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions specs/analog/decks/sar_kick_aperture.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
The golden comparator's aperture: how much a step of its input at time tau still matters to the decision (M4e-kick, #10942)
* specs/analog/decks/sar_kick_aperture.cir -- sar_kick_edge.cir (the golden comparator, SAR_logic and clock_gen with the two gates on ideal sources, the plates' tracking history tp = 14 ns) with ONE thing
* added: the gate of VDP takes a step of dv = 1 mV at the time tau (20 ps ramp), and the decision is read as the difference of the latch's two outputs, v(dp) - v(dn), 4.8 ns after the
* clock edge's 0.1 V crossing (104.107 ns; 5.0 ns after gives the same ratios). The latch amplifies a small difference of its inputs exponentially, so the response is proportional to dv for a
* small step and the ratio of the response to a step at tau to the response to a step before the edge is the share of the decision that the input still decides at tau: 1 until the pair
* begins to lose its gain and 0 once the latch has locked. The kick of the comparator's own plates moves VDP - VDN through that window, and sar_kick_net.t27 weighs it by this aperture.
* The unperturbed run has dp = dn (the plates are alike); the steps at 98.3069 ns (before the edge), at 0.5 mV and at 2 mV, give the same response to 0.1 percent (LINEAR rows).
* Paths are NOT in this file: IHP_PDK, IHP_OSDI and SAR_GOLDEN_SUBCKTS as in sar_kick_edge.cir. Run: ngspice -b sar_kick_aperture.cir (ngspice-47, about two minutes)
* It prints one row per tau between BEGIN aperture and END aperture: tau - 99.3069 ns (the clkc 0.1 V crossing of the unperturbed run) in ns, and the response in volts.
.param vg=0.742
.param tp=14n
.param tau=1
.param dv=0
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerMOSlv.lib mos_tt
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerCAP.lib cap_typ
.include $SAR_GOLDEN_SUBCKTS
VDD4 vdda 0 1.5
VDD6 vdd 0 1.5
VDD1 vss 0 0
V2 c 0 0
V5 b 0 0
V6 a 0 0
VCLKS clks 0 PULSE(0 1.5 0n 2n 2n 80n 500n)
BPD vdpi 0 V = {vg}*(1-exp(-time/{tp}))+{dv}*min(max((time-{tau})/20p,0),1)
BND vdni 0 V = {vg}*(1-exp(-time/{tp}))
VMP vdpi vdp 0
VMN vdni vdn 0
x3 vocp vocn valid vdp vdn clkc vdd 0 dynamic_comparator_top
x7 ck3 ck11 ck7 ck2 ck6 ck10 ck1 ck9 ck5 ck8 ck4 vdd 0 vdd valid 0 clks SAR_logic
x4 vdd clkc 0 clks valid ck1 a b c clock_gen
C9 clkc 0 4f
C10 vocp 0 4f
C11 valid 0 4f
C12 vocn 0 4f
C13 clkc 0 4f
C14 clks 0 4f
C15 valid 0 4f
C16 ck1 0 4f
C17 a 0 4f
C18 b 0 4f
C19 c 0 4f
C20 clks 0 4f
C21 valid 0 4f
.options temp=50
.options klu
.control
pre_osdi $IHP_OSDI/psp103.osdi
pre_osdi $IHP_OSDI/psp103_nqs.osdi
pre_osdi $IHP_OSDI/r3_cmc.osdi
pre_osdi $IHP_OSDI/mosvar.osdi
pre_osdi $IHP_OSDI/cap_cmomi.osdi
pre_osdi $IHP_OSDI/cap_cmomf.osdi
set num_threads=4
echo BEGIN aperture
foreach tauv 98.3069n 102.3069n 102.4319n 102.5569n 102.6819n 102.8069n 102.9319n 103.0569n 103.1819n 103.3069n 103.4319n 103.5569n 103.6819n 103.8069n 103.9319n 104.0569n 104.1819n
alterparam vg = 0.742
alterparam tp = 14n
alterparam tau = $tauv
alterparam dv = 0.001
reset
tran 0.05n 107n
meas tran dd find v(x3.dp) at=104.1069n
meas tran de find v(x3.dn) at=104.1069n
echo APERTURE $tauv
print dd de
end
foreach dvv 0 0.0005 0.002
alterparam vg = 0.742
alterparam tp = 14n
alterparam tau = 98.3069n
alterparam dv = $dvv
reset
tran 0.05n 107n
meas tran dd find v(x3.dp) at=104.1069n
meas tran de find v(x3.dn) at=104.1069n
echo LINEAR $dvv
print dd de
end
echo END aperture
.endc
.end
46 changes: 46 additions & 0 deletions specs/analog/decks/sar_kick_cnode.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
The capacitance the bottom-plate drivers hang on an idle bit's two plate nodes (M4e-kick, #10942)
* specs/analog/decks/sar_kick_cnode.cir -- one bit of the golden SAR ADC's bottom-plate logic, idle: DAC_control (its inverter, its tgate x2 to VCM, the tgates x3 and x8, two dffs) and
* neg_bottom_plate_logic (the tgates x11 and x10 and x15, the inverters x12, x13, x14) of the uberWAVE golden deck (wp2-parser/golden/top.spice, GPL-2.0: read at run time, never
* vendored; the subcircuits come from the run-time file SAR_GOLDEN_SUBCKTS, made as in sar_off_base.cir), with its clock CK11 low so that the bit is idle: Bit (the P half's plate node) is held at VCM
* by the tgate x2 and Bit_n (the N half's) reaches Bit through the tgate x11. The two plate nodes are the two ports; the DAC's capacitors are NOT here (they are the capacitor network's own),
* so what is measured is what the drivers add to the nodes: junction, overlap and channel charge of the devices of the golden subcircuits at the idle bias, through the PSP103 model (OSDI).
* Each port is held at 0.75 V by a source with a 1 V small-signal part in turn and the current of both sources is read at 100 MHz (and 300 MHz): the admittance matrix Y = G + j w C of the two-port.
* It prints, between BEGIN y and END y, one row per run (port 1 excited, port 2 excited) and frequency: the real and imaginary parts of the two currents into the ports, in A (volts are 1).
* The network model reads C11 + C12 (Bit to ground), C22 + C21 (Bit_n to ground) and -C12 (Bit to Bit_n), C_ij = Im Y_ij / w; Re Y11 is 1 / R(x2) + 1 / R(x11) and -Re Y12 = 1 / R(x11):
* the tgates' resistances (sar_off_ron.cir measures one at 10 mV) again, in situ.
* Paths are NOT in this file: IHP_PDK, IHP_OSDI and SAR_GOLDEN_SUBCKTS as in sar_off_base.cir. Run: ngspice -b sar_kick_cnode.cir (ngspice-47, seconds). TEMP 50 as in the golden deck.
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerMOSlv.lib mos_tt
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerCAP.lib cap_typ
.include $SAR_GOLDEN_SUBCKTS
VDD vdd 0 1.5
VCM vcm 0 0.75
VCK ck 0 0
VIN vin 0 0.75
VCLK clks 0 0
VST set 0 0
VRS reset 0 0
XD vdd 0 sar vcm bitp vin ck set reset clks DAC_control
XN vdd 0 ck bitp bitn neg_bottom_plate_logic
VPB bitp 0 0.75 ac 1
VNB bitn 0 0.75 ac 0
.options temp=50
.control
pre_osdi $IHP_OSDI/psp103.osdi
pre_osdi $IHP_OSDI/psp103_nqs.osdi
set numdgt=8
echo BEGIN y
foreach fr 1e8 3e8
alter vpb ac = 1
alter vnb ac = 0
ac lin 1 $fr $fr
echo PORT1 $fr
print i(vpb) i(vnb)
alter vpb ac = 0
alter vnb ac = 1
ac lin 1 $fr $fr
echo PORT2 $fr
print i(vpb) i(vnb)
end
echo END y
.endc
.end
80 changes: 80 additions & 0 deletions specs/analog/decks/sar_kick_edge.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
The golden comparator and its clock generator at the first decision's clock edge, the two gates held (M4e-kick, #10942)
* specs/analog/decks/sar_kick_edge.cir -- the golden dynamic_comparator_top, SAR_logic and clock_gen of the SAR ADC deck of uberWAVE (wp2-parser/golden/top.spice, GPL-2.0: fetched at run
* time, never vendored; the subcircuits come from the run-time file SAR_GOLDEN_SUBCKTS, made as in sar_off_base.cir) with the two top plates replaced by ideal sources, so that what the
* input pair does at the clock edge is read with nothing in the way: the tail node net1, the drains ap and an, and the charge the gates take from the plates. The sources reach the plates'
* level of the first decision, vg = 0.742 V (VDP 0.739 V and VDN 0.745 V in sar_off_base.cir), along vg (1 - exp(-t / tp)) with tp = 14 ns: the tracking switch of the golden deck settles the
* plates in that time, and net1, which floats in the clock's low phase and is charged by the pair's subthreshold current from the drains, is where that history leaves it at the edge:
* 0.654 V here at 97.6 ns, 0.659 V in sar_off_base.cir at 98 ns (read from its x3.x1.net1). Each gate's source is read through a zero-volt meter (VMP, VMN): its current is the gate current.
* Everything else is sar_off_base.cir's: supplies, the clks pulse of the sampling clock, the 4 fF loads on clkc, the comparator outputs, valid, ck1, a b c and clks; the first decision's
* clock edge comes 99.3 ns after the start (clkc crosses 0.1 V at 99.307 ns and 0.75 V at 103.118 ns in this deck, 103.102 ns in sar_off_base.cir with the plates moving).
* Paths are NOT in this file: IHP_PDK (the IHP-Open-PDK checkout, commit 21133f21), IHP_OSDI (the directory with the compiled psp103.osdi, psp103_nqs.osdi, r3_cmc.osdi, mosvar.osdi,
* cap_cmomi.osdi, cap_cmomf.osdi) and SAR_GOLDEN_SUBCKTS, in the environment. Run: IHP_PDK=<checkout> IHP_OSDI=<osdi dir> SAR_GOLDEN_SUBCKTS=<file> ngspice -b sar_kick_edge.cir (ngspice-47, seconds)
* It prints, between BEGIN wave and END wave, 67 rows at 0.1 ns from 97.8 ns to 104.4 ns (index k: time 97.8 ns + 0.1 ns k): the tail node n1 and the drain ap in volts, an
* (equal to ap to 1 uV: the plates are alike) and the charge the gate of VDP has taken from its source since 97.8 ns, in coulomb, qg = the integral of i(VMP) dt; and the crossing times tc01, tc075.
.param vg=0.742
.param tp=14n
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerMOSlv.lib mos_tt
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerCAP.lib cap_typ
.include $SAR_GOLDEN_SUBCKTS
VDD4 vdda 0 1.5
VDD6 vdd 0 1.5
VDD1 vss 0 0
V2 c 0 0
V5 b 0 0
V6 a 0 0
VCLKS clks 0 PULSE(0 1.5 0n 2n 2n 80n 500n)
BPD vdpi 0 V = {vg}*(1-exp(-time/{tp}))
BND vdni 0 V = {vg}*(1-exp(-time/{tp}))
VMP vdpi vdp 0
VMN vdni vdn 0
x3 vocp vocn valid vdp vdn clkc vdd 0 dynamic_comparator_top
x7 ck3 ck11 ck7 ck2 ck6 ck10 ck1 ck9 ck5 ck8 ck4 vdd 0 vdd valid 0 clks SAR_logic
x4 vdd clkc 0 clks valid ck1 a b c clock_gen
C9 clkc 0 4f
C10 vocp 0 4f
C11 valid 0 4f
C12 vocn 0 4f
C13 clkc 0 4f
C14 clks 0 4f
C15 valid 0 4f
C16 ck1 0 4f
C17 a 0 4f
C18 b 0 4f
C19 c 0 4f
C20 clks 0 4f
C21 valid 0 4f
.options temp=50
.options klu
.control
pre_osdi $IHP_OSDI/psp103.osdi
pre_osdi $IHP_OSDI/psp103_nqs.osdi
pre_osdi $IHP_OSDI/r3_cmc.osdi
pre_osdi $IHP_OSDI/mosvar.osdi
pre_osdi $IHP_OSDI/cap_cmomi.osdi
pre_osdi $IHP_OSDI/cap_cmomf.osdi
set num_threads=4
tran 0.05n 107n
meas tran tc01 when v(clkc)=0.1 rise=1
meas tran tc075 when v(clkc)=0.75 rise=1
linearize v(x3.x1.net1) v(x3.x1.ap) v(x3.x1.an) i(vmp)
let qint = integ(i(vmp))
let n1w = unitvec(67)
let apw = unitvec(67)
let anw = unitvec(67)
let qgw = unitvec(67)
let k = 0
while k < 67
let j = 1956 + 2*k
let n1w[k] = v(x3.x1.net1)[j]
let apw[k] = v(x3.x1.ap)[j]
let anw[k] = v(x3.x1.an)[j]
let qgw[k] = qint[j] - qint[1956]
let k = k + 1
end
set numdgt=8
set noprintscale
echo BEGIN wave
print n1w apw anw qgw
echo END wave
.endc
.end
66 changes: 66 additions & 0 deletions specs/analog/decks/sar_kick_qg.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
The gate charge of the comparator's input device, bulk on ground, at 50 C: Q_G(Vg, Vs, Vd) on three gate levels, 25 x 25 each (M4e-kick, #10942)
* specs/analog/decks/sar_kick_qg.cir -- the input pair of the golden dynamic comparator (XM3, XM4: sg13_lv_nmos W 1.0 um, L 0.45 um, 36 in parallel) has its bulk on VSS and its source on the tail
* node, which sits 0.2 .. 0.7 V above ground while it falls at the clock edge; M3c's gate-charge table (psp103_q_tt.cir, TT_QG_N) is for the bulk tied to the source and 27 C. This deck is that
* recipe with the two things the comparator has: the bulk at 0 V and TEMP 50 (the golden deck's `.options temp=50`), and with the gate as a third axis. The gate sits at one of three levels,
* Vg = 0.742 V + (jg - 1) * 25 mV (jg = 0, 1, 2: 0.717, 0.742, 0.767 V; the plates of the first decision rest at 0.74 V and move by tens of millivolts), the SOURCE is on a staircase of 25 levels,
* Vs = ix * 31.25 mV, and the drain on 25 levels, Vd = iy * 62.5 mV; the index is jg * 625 + ix * 25 + iy. Each node of the grid is visited from ONE origin (Vg = 0.742 V, Vs = Vd = 0) for 10 ns
* and the bias returns to the origin for 10 ns, and the gate's terminal current at the end of the return step, against the one before the first jump, is the gate charge
* Q_G(Vg, Vs, Vd) - Q_G(0.742, 0, 0) of M3c's recipe: Q(B) - Q(A) = (i_A - i_return) dt (the gate current is a few pA at the origin, where the device conducts with Vds = 0, so no
* DC current needs subtracting). Because the origin is the same for the three levels, a difference of two levels is the charge a change of the gate moves. The unit and the offset are M3c's:
* one unit is Q / 500 fF in 2^-24 V (2.98e-20 C), entry = nint(2e12 * 2^24 * (Q(B) - Q(A))) + 2^21, for the one device (m = 1); the comparator's pair is 36 of them.
* Model: IHP-Open-PDK commit 21133f219b1a6da10d803e345761e77415ceff40, mos_tt (PSP 103.6), the OSDI models psp103.osdi and psp103_nqs.osdi compiled from the same commit.
* Paths are NOT in this file: ngspice reads IHP_PDK (the checkout) and IHP_OSDI (the directory of the compiled .osdi files).
* Run: IHP_PDK=<checkout> IHP_OSDI=<osdi dir> ngspice -b sar_kick_qg.cir (ngspice-47, seconds)
* It prints, between BEGIN qg and END qg, the 1875 entries, and between BEGIN cap_o and END cap_o the gate capacitances ngspice itself reports at one operating point (Vg 0.742, Vs 0.4,
* Vd 1.3, in aF) as a cross-check.
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerMOSlv.lib mos_tt
.func kst() {nint(time/1e-8)}
.func nd() {max(floor(kst()/2)-1,0)}
.func act() {(time<1e-3)*(kst()>=2)*((kst()-2*floor(kst()/2))==0)}
.func jgf() {floor(nd()/625)}
.func ixf() {floor((nd()-625*jgf())/25)}
.func iyf() {nd()-625*jgf()-25*ixf()}
BSN tsn 0 V = act()*0.03125*ixf()
BDN tdn 0 V = act()*0.0625*iyf()
BGN tgn 0 V = 0.742+act()*0.025*(jgf()-1)
VMGN tgn tgnn 0
XTN tdn tgnn tsn 0 sg13_lv_nmos w=1.0u l=0.45u ng=1 m=1
* a second copy at one fixed bias, for ngspice's own capacitances
VSO so 0 0.4
VDO dO 0 1.3
VGO go 0 0.742
XMO dO go so 0 sg13_lv_nmos w=1.0u l=0.45u ng=1 m=1
.options temp=50
.options reltol=1e-6 vntol=1e-9 abstol=1e-14
.options method=gear maxord=1 trtol=1e7 itl4=200
.control
pre_osdi $IHP_OSDI/psp103.osdi
pre_osdi $IHP_OSDI/psp103_nqs.osdi
set numdgt=10
set noprintscale
op
let c_gg = nint(@n.xmo.nsg13_lv_nmos[cgg] * 1e18)
let c_gsol = nint(@n.xmo.nsg13_lv_nmos[cgsol] * 1e18)
let c_gdol = nint(@n.xmo.nsg13_lv_nmos[cgdol] * 1e18)
echo BEGIN cap_o
print c_gg c_gsol c_gdol
echo END cap_o
tran 7.8125n 37.6u 0 10n
let g0 = i(vmgn)[8]
let qgn = unitvec(1875)
let tchk = abs(time[8] - 1e-8)
let k = 0
while k < 1875
let r = 2*k + 10
let tchk = max(tchk, abs(time[r] - (2*k+3)*1e-8))
let qgn[k] = nint((g0 - i(vmgn)[r]) * 1e-8 * 2e12 * 16777216) + 2097152
let k = k + 1
end
echo BEGIN qg
print qgn
echo END qg
echo BEGIN tchk
print tchk
echo END tchk
.endc
.end
Loading