We created a schematic for the posted NAND2 layout (with the electrically correct connections (treating drain and source as asymmetrical):
We could not find any SPICE model cards for a channel length L=2u (that large a process has
not been used in integrated circuit design for thirty years or more), so we used BSIM4 model cards for nmos and pmos (and provide a link to those files at our GitHub account) suitable for the NAND2 (and INV) 45nm PDK cell layout (and power supply voltage, operating frequency and load capacitance from the relevant standard cell library).
We write circuit files to run in Ngspice-27. Hopefully the code comments and discussion here will make adapting the methods to other SPICE variations.
MOSFETs in CMOS gates are voltage-controlled switches so it would be inappropriate to drive them with a current source if the intent is to measure gate input capacitance seen by another CMOS driving circuit (that is the goal we have set here). Accordingly, we use roughly the output \$R_{ds}\$ of a CMOS circuit for our standard library 45 nm process, \$1 \, \mathrm{k}\Omega\$, resistor between the pulse generator \$^+\$lead in series with the connection to the NAND2 X1 input (in1) input which is our test target for dynamic input capacitance.
We will use the so-called differential form of the electrostatics definition \$C =Q/V\$ of capacitance:
$$ C = \frac{dQ}{dV}
$$
Ngspice circuit file implementing a NAND2 (X1) standard cell circuit with BSIM4 model cards (link to those at end of article)
SIMPLE CAPACITANCE MEAS OF NAND INPUT CAP
* a less sophisticated simple input capacitance
* driving gate with voltage pulse
* and calculating charge delivered
* meas capacitance of NAND2_X1 gate input 1
* using Ngspice-27 Creation Date: Tue Dec 26 17:10:20 UTC 2017
* using BSIM4 level=54 mosfet models from process file
* /FreePDK45/ncsu_basekit/models/hspice
* /tran_models/models_nom/NMOS_VTL.inc
* in which we updated the version statement from 4.0 to 4.8
* and enabled RF high speed support
* the W and L dimensions of INV_X1 and NAND2_X1
* come from NCSU FreePDK 45nm
* used by Christopher Torng 2019 for
* a 45nm ASIC design kit for mflowgen
* we use ngspice 25 degree C default circuit temperature,
* and vdd 1.10v per
* NangateOpenCellLibrary_typical
* Build Date: Thursday Feb 17 15:07 2011 library
*********************************
* PARAMETERS for command lines,
* CSPARAMETERS for lines within control section or echos/prints
* refer to ngspice-27 manual for syntax
* Simulation time setup
* desired pulse train frequency in Hz
.param testfreq=1000e6
* printable as MHz
.csparam testfreqPrintable={testfreq/1e6}
* the period is then 1/frequency in seconds
.param testperiod='1/testfreq'
.csparam testperiodctl={testperiod}
.csparam testperiodctl2={testperiod*2}
*.csparam testperiodSmallerForPlotctl={testperiod*0.7}
.csparam testperiodSmallerForPlotctl={testperiod*1.1}
* how many cycles at specified frequency should be analyzed
.param testcycles='5'
* length of the simulation in seconds will be
* number of cycles times period
.param ttime='testperiod*testcycles'
.csparam ttimectl={ttime}
* how many simulation steps desired:
.param numberOfStepsInSim=100000
* resolution is length of simulation divided by steps
.param transstepsize='ttime/numberOfStepsInSim'
* power supply DC voltage, using
* Nangate typical corner Vdd=1.10 v, see
* NangateOpenCellLibrary_typical Build Date:
* Thursday Feb 17 15:07 2011
.param DCsupplyVoltage=1.10
* want to space multiple voltage plots clearly,
* so get ceiling of DCsupplyVoltage
.param PlotMultiVoltsSpacer=(DCsupplyVoltage+.9)
* need a csparam form to use in the control section
.csparam PlotMultiVoltsSpacerForCTL={PlotMultiVoltsSpacer}
* similarly, need DCsupplyVoltage param that works in control section
.csparam DCsupplyVoltageForCTL={DCsupplyVoltage}
* for y limit if plot n traces together, say n=5
.param numOfVoltTraces=5
.csparam DCsupplyVoltageForYLIM={PlotMultiVoltsSpacer*numOfVoltTraces}
* pulse train input stimulus parameters
* note rise/fall based on 20% pulse width
.param RiseFallPercent=0.20
.param HalfPeriod='(testperiod/2)'
.param PulseWidth='(HalfPeriod)'
.param TriseOrFall='(PulseWidth*RiseFallPercent)'
.csparam TriseOrFallPrintable={TriseOrFall*1}
* load capacitance for NAND output
.param NANDLoadCapacitance=59fF
.csparam NANDLoadCapacitancePrintable={NANDLoadCapacitance*1e15}
**************************************
* BSIM4 level=54 mosfet models from
* 2006 45nm_bulk.pm process file
* which we updated the version statement from 4.0 to 4.8
.include modelcard.nmos
.include modelcard.pmos
* use NMOS_VTL for the model name nmos in instantiation
* use PMOS_VTL for the model name pmos in instantiation
**************************************
* POWER SUPPLY
* NAND gate power supply:
vdd3 vddnand 0 {DCsupplyVoltage}
* the NAND subckt simply uses global gnd node 0
*********************************************
* CREATE the NAND gate whose input gate A will be
* target capacitance
*** SUBCIRCUIT DEFINITION
* global gnd 0 not included in parameter list
.SUBCKT NAND in1 in2 out VDD
*
* PMOS parallel PUN pair
* nd ng ns nb model
M3 out in1 vdd vdd PMOS_VTL W=0.630000U L=0.050000U
M4 out in2 vdd vdd PMOS_VTL W=0.630000U L=0.050000U
* NMOS series PDN pair
* nd ng ns nb model
M1 net.1 in2 0 0 NMOS_VTL W=0.415000U L=0.050000U
M2 out in1 net.1 0 NMOS_VTL W=0.415000U L=0.050000U
*
.ENDS NAND
* above we use the W and L dimensions of NAND2_X1
* from NCSU FreePDK 45nm
* from Christopher Torng 2019 45nm ASIC design kit for mflowgen
*
* INSTANTIATE a NAND gate X3 using the SUBCKT:
* in1 in2 out VDD
X3 in1 in2 out vddnand NAND
********************************************
*********************************************
* MEASUREMENT CONNECTIONS
* measure effective capacitance of the in1 input to NAND gate
* when driven voltage pulse train
* provide low resistance path
* to NAND input 1 in1 from pulse
* source, use approx. CMOS output R
* as voltage pulse source resistance
RTOTARGETC PulseInput in1 1000
* tie unused NAND input in2 of NAND to vddnand
RX32 in2 vddnand 10k
* LOAD the NAND X3 output:
CLOAD out 0 {NANDLoadCapacitance}
********************************************
* CONTROL SECTION
.control
* syntax note: initial plus sign is extension of previous line
* to keep columns less than equal 66 for printing
* run transient analysis defined outside the control section
run
* make the plot white background instead of default black
set color0 = white ; plot window -background color
set color1 = black ; plot window -grid and text color
* thinner grid and plot lines?
set xbrushwidth=0.5
* plot 2 cycles NAND output and in1 NAND input
plot in1 out xl 0 $&testperiodctl2
+ title "NAND input (in1, in2 at VDD) and output, 2 cycles"
* measure input capacitance of the NAND:
let rcurrent = ( (pulseinput - in1) / @rtotargetc[resistance] )
echo "charge transferred to NAND input: (Coulombs)"
meas tran incurlh INTEG rcurrent from=0 to=$&TriseOrFallPrintable
echo "voltage change on NAND input: (Volts)"
meas tran maxin1 MAX in1 from=0 to=$&TriseOrFallPrintable
echo ""
echo "capacitance of NAND input measured, fF:"
let NANDincap = (incurlh / maxin1)*1e15
print NANDincap
echo ""
settype current rcurrent
plot rcurrent xl 0 $&TriseOrFallPrintable
+ title "NAND in1 current L to H"
plot in1 xl 0 $&TriseOrFallPrintable
+ title "NAND in1 gate voltage L to H"
****
echo "(Nangate typical build library suggests"
echo "NAND2_X1 A1 input is 1.599 fF)"
echo ""
echo "Load capacitance on NAND output: "
echo $&NANDLoadCapacitancePrintable " fF"
echo ""
echo "Test frequency was " $&testfreqPrintable " MHz"
echo "Input rise/fall time was " $&TriseOrFallPrintable " s"
echo "pulse source output impedance: (ohms)"
print @RTOTARGETC[resistance]
echo "Vdd supply voltage was "
echo $&DCsupplyVoltageForCTL " volts DC"
.endc
*********************************************
*********************************************
* PULSE DRIVE of NAND input 1
VIN1 PulseInput 0 PULSE(0 {DCsupplyVoltage}
+ 0 {TriseOrFall} {TriseOrFall} {PulseWidth} {testperiod})
*******************************************
* transient analysis
.tran 'transstepsize' 'ttime'
********************************************
.END
In the Ngspice-27 code above (in the CONTROL section; note that we give Ngspice variable names from code above in parentheses) we:
- obtain the voltage drop across the pulse source resistor (rtotargetc) by taking the difference of the voltage from the pulse generator ideal voltage source (pulseinput) and the voltage at the NAND2 input (in1). This is a vector (a matrix of data with an element for each time step of the simulation) which will be the voltage drop across the source resistance for each simulation time step (because we are running a transient analysis)
- obtain the current flow (rcurrent) into the NAND2 input in1 by dividing the voltage drop across the pulse source resistor (the vector above) by the scalar resistance of the source (rtotargetc).
- integrate that gate input current (the rcurrent vector) from zero to the rise time of the pulse stimulus (TriseOrFallPrintable). store this in variable (incurlh). This is the charge transferred to the gate input over the interval of integration.
- obtain the voltage change from zero to the maximum, i.e., the maximum value from zero to the rise time of the pulse stimulus (TriseOrFallPrintable). store that in variable (maxin1).
- divide the charge transferred (incurlh) by the voltage change (maxin1) and echo that capacitance value to the screen.
Terminal output from the Ngspice-27 code run above:
charge transferred to NAND input: (Coulombs)
incurlh = 1.39093e-15 from= 0.00000e+00 to= 1.00000e-10
voltage change on NAND input: (Volts)
maxin1 = 1.088130e+00 at= 1.000000e-10
capacitance of NAND input measured, fF:
nandincap = 1.278276e+00
(Nangate typical build library suggests
NAND2_X1 A1 input is 1.599 fF)
Load capacitance on NAND output:
59 fF
Test frequency was 1000 MHz
Input rise/fall time was 1E-10 s
pulse source output impedance: (ohms)
@rtotargetc[resistance] = 1.000000e+03
Vdd supply voltage was
1.1 volts DC
We measure \$1.278276 \, \mathrm{fF}\$ above, \$20 \%\$ lower than Nangate standard library typical corner suggested value of \$1.599 \, \mathrm{fF}\$. CBCM (charge-based capacitance measurement) is more accurate (within a few percent), but the CBCM method requires more circuit code.
Why test frequency of \$1 \, \mathrm{GHz}\$? We made use of the familiar relation between rise time \$t_r\$ and signal \$-3 \, \mathrm{dB}\$ cutoff frequency, \$f_{-3 \, \mathrm{dB}}=0.35/t_r\$.
One of the Nangate stdcells-databook (for our 45nm CMOS process) applicable test input rise time specifications for our typical corner circuit NAND2_X1 loaded with \$C_L = 59.3567 \, \mathrm{fF}\$ is \$0.1985 \, \mathrm{ns}\$. \$t_r = 0.1985 \, \mathrm{ns}\$ is then roughly equivalent to a clock speed of \$1.8 \, \mathrm{GHz}\$.
$$ 0.35 / 0.1985 \, \mathrm{ns} = 1.8 \, \mathrm{GHz}
$$
Transit time estimates also put us in this general neighborhood, so we went with the conservative \$1\, \mathrm{GHz}\$, maximum clock estimates not necessarily being the reliably usable frequency of operation. Edge rate enters in also. You will note in the Ngspice-27 code that we automate the specification of rise/fall time of the input signal, using 20% of the pulse width, the latter being half the test frequency period. The frequency and rise time used is printed in the terminal after a run (as seen above, i.e., rise time was \$100 \, \mathrm{ps}\$ and test frequency \$1\, \mathrm{GHz}\$).
Why \$V_{dd} = 1.1 \, \mathrm{V}\$? That is the specified voltage supply for this typical corner in 45nm CMOS (VTL).
What about output resistance of the NAND2 gate? We treat the output voltage waveform of the switch as an exponential with a time constant defined by \$R_S\$ and \$C_{eq}\$.
$$
V_o = V \left[ 1 - \exp \left(\frac{-t}{R_S C_{eq}} \right) \right]
$$
where \$R_S\$ is the output impedance of the gate and \$C_{eq}\$ the equivalent capacitive load on the output. For our purposes, \$C_{eg}=C_L= 59 \, \mathrm{fF}\$ (to be clear, we hang a \$59 \, \mathrm{fF}\$ capacitor on the output of the NAND gate, as we did above), which should dominate any intrinsic capacitance of the PMOS or NMOS transistors.
Considering the equivalent output resistance \$R_S=R_{DS}\$ of the PMOS transistor in the output transition from LOW to HIGH, our time interval will be the rise time \$t_r\$ which we define here as the time required to rise from \$0.1\$ to \$0.9\$ of the final output voltage at the NAND2 output. We solve for \$t_r\$ using the equation above:
$$
\begin{align}
\frac{V_o}{V} &= 0.9 = \left[ \exp \left(\frac{-t_{0.9V}}{R_S C_{eq}} \right) \right]
\nonumber \\[1ex]
\ln(0.9) &= -0.1053 = \left(\frac{-t_{0.9V}}{R_S C_{eq}} \right) \quad \quad
\Longrightarrow 0.1053R_S C_{eq} = t_{0.9V}
\nonumber \\[1ex]
\frac{V_o}{V} &= 0.1 = \left[ \exp \left(\frac{-t_{0.1V}}{R_S C_{eq}} \right) \right]
\nonumber \\[1ex]
\ln(0.1) &= -2.3026 = \left(\frac{-t_{0.1V}}{R_S C_{eq}} \right) \quad \quad
\Longrightarrow 2.3026 R_S C_{eq} = t_{0.1V}
\nonumber \\[1ex]
t_r &= R_S C_{eq} \left( t_{0.1V} - t_{0.9V}\right) = 2.19722 (R_S C_{eq})
\approx 2.2 (R_S C_{eq}) \nonumber \\[1ex]
\end{align}
$$
Knowing \$C_{eq}=C_L\$, if we measure the times at which the \$0.1\$ and \$0.9\$ voltage points on the rising output transition occur to obtain \$t_r\$, we then obtain an estimate of the PMOS drain source resistance with \$R_S= R_{DS} = t_r /(2.2 C_L\$.
First we obtain the final voltage of our output rising signal, selecting an interval to measure on where NAND (out) appears to be leveling out, e.g., \$t=0.3\$ to \$t=0.4 \, \mathrm{ns}\$ using Ngspice-27 interactive commands in the terminal window after running the simulation:
ngspice 1 -> meas tran maxinvolt MAX_AT out from=0.300n to=0.400n
maxinvolt = 3.999750e-10 with= 1.094780e+00
It appears our final voltage on NAND (out) rising will be \$1.09478 \, \mathrm{V}\$. We then calculate the \$0.1\$ and \$0.9\$ fractions of that voltage, making use of Ngspice interactive calculator capability:
ngspice 1 -> print 1.094780e+00*0.1
1.094780e+00*0.1 = 1.094780e-01
ngspice 1 -> print 1.094780e+00*0.9
1.094780e+00*0.9 = 9.853020e-01
We now have the two output voltage trigger points, so will enter the Ngspice command to measure the time difference between the output out at those two points:
meas tran tdiff TRIG out VAL=1.094780e-01 RISE=1 TARG out VAL=9.853020e-01 RISE=1
And response in terminal:
tdiff= 1.231943e-10 targ= 2.910126e-10 trig=1.678183e-10
We obtain \$t_r = 123.1943 \, \mathrm{ps}\$ for the \$\Delta t\$ (between \$t_{0.1V}\$ and \$t_{0.9V}\$). Now we apply our equation above using our load capacitance value of \$C_L= 59 \, \mathrm{fF}\$:
ngspice 1 -> print 1.231943e-10/(2.2*59e-15)
1.231943e-10/(2.2*59e-15) = 9.491086e+02
We obtain an estimated average \$R_{ds}= 949 \, \Omega\$ for the single M3 PMOS transistor (see NAND schematic given earlier) in saturated pullup mode, i.e., charging the output capacitance \$C_L\$.
For a detailed discussion of the above circuits and measurements, including:
- standard cell libraries parameters and the FreePDK45, including the CDL text of the NAND2 circuit and the Nangate suggested values we used
- relevant CMOS layout making context with schematic and silicon clear
- bandwidth estimation (multiple methods)
- output resistance (multiple methods)
- input capacitance measurement (multiple methods)
- propagation delay
- brief examination of the BSIM4 MOSFET capacitance model, including the intrinsic core model (presenting the Ward-Dutton transcapacitance matrix), the BSIM4 RF (high-speed) settings we used, and for the curious, a look under the hood as it were, graphing some of the internal BSIM4 capacitance and charge variables
- implementation of the charge-based capacitance measurement presented by Dennis Sylvester and Chenming Hu “Analytical Modeling and Characterization of Deep-Submicrometer Interconnect,” PROCEEDINGS OF THE IEEE 89 (2001)
with all reference cites (many including url's), see our paper hosted at GitHub (along with the nmos and pmos BSIM4 model cards we used, multiple Ngspice-27 circuit files, copies of the Ngspice-27 manual to facilitate understanding the code):
the article and circuit files listed
CBCMcmosArticle.pdf, the article
We recommend that you download and view in the article in apdf viewer rather than a browser to preserve the hyperlinked document cross-references, table of contents, and reference cites.