A self-contained voltage-source/resistor/diode test aborts with Timestep too small at the diode's temperature-adjusted sidewall forward-capacitance transition. Changing FCS moves the failure to the corresponding new transition voltage; setting only CJSW to zero allows the transient to complete.
The source analysis below suggests a discontinuity in sidewall depletion charge: the above-threshold sidewall expression appears to reuse the bottom-junction integration constant. This is a suspected cause, not a validated C-source fix.
The reproducer requires no external PDK installation, MOSFET model, bandgap schematic, behavioral device, or zero-volt current probe.
Mon Jul 27 13:15:13 UTC 2026.-n to skip startup files.The attached results are from ngspice 46. This report does not establish whether ngspice 47 or current development sources are affected. The source discussion refers specifically to the ngspice-46 tag. No C-source patch has been validated.
Save the following as diode_sidewall.spice and run it in a fresh directory:
ngspice -n -b -o reproduce.log diode_sidewall.spice
The netlist writes trace.txt in the working directory.
Diode sidewall-charge transition reproducer, ngspice 46
* Diode coefficients from the public GF180MCU nwp model.
* Copyright 2022 GlobalFoundries PDK Authors. Apache-2.0.
* No external model library or bandgap schematic is needed.
.model nwp d
+ cj=0.00014917
+ cjsw=5.8113e-010
+ cta=0.0023998
+ ctp=0.0010977
+ level=3
+ mj=0.33979
+ mjsw=0.2257
+ pb=0.5755
+ php=0.55456
+ tlevc=1
+ tpb=0.0027641
+ tphp=0.0019629
+ tref=25
VDRV drive 0 PWL(0 0 1u 0 2u -0.5 3u -0.5 4u 0 5u 0)
RDRV drive node 50k
DTEST 0 node nwp area=1.56942828e-11 pj=2.17286e-05
.temp -40
.options tnom=25 method=gear reltol=1e-5 vntol=1e-7 abstol=1e-13 itl4=200
.control
set noaskquit
set num_threads=1
set numdgt=15
set wr_singlescale
set wr_vecnames
save all @dtest[id] @dtest[charge] @dtest[cd] @dtest[capcur]
tran 1e-09 5e-06 0 1e-09
let d0 = v(node)
let d1 = @dtest[id]
let d2 = @dtest[charge]
let d3 = @dtest[cd]
let d4 = @dtest[capcur]
wrdata trace.txt d0 d1 d2 d3 d4
quit
.endc
.end
The embedded diode coefficients are from the public GF180MCU nwp model, Copyright 2022 GlobalFoundries PDK Authors, Apache-2.0. No separate model library is required.
The depletion-charge function should remain continuous through the sidewall capacitance transition, with its voltage derivative matching the reported capacitance. The transient should reach the requested stop time of 5 us.
The baseline run stops at approximately 1.68687852 us:
Doing analysis at TEMP = -40.000000 and TNOM = 25.000000
Using SPARSE 1.3 as Direct Linear Solver
No. of Data Rows : 1723
doAnalyses: TRAN: Timestep too small; time = 1.68688e-06, timestep = 1.25e-21: trouble with node "node"
tran simulation(s) aborted
The final saved values are:
time = 1.686878519986614e-6 s
v(node) = -0.3430371499999962 V
@dtest[charge] = 5.045068295795775e-15 C
@dtest[cd] = 1.608818548582263e-14 F
The diode anode is grounded, so the forward diode voltage is +0.34303715 V at the failure.
The process returns exit status 0 despite the transient abort. Please check the log and final trace time rather than relying on exit status alone.
Each change below is applied independently to the original netlist:
| Case | Change from baseline | Result |
|---|---|---|
| Baseline | None: -40 C, default FCS=0.5 | Aborts at forward diode voltage 0.343037150 V |
| Temperature control | Change only .temp -40 to .temp 25 |
Aborts at 0.279242900 V |
| Transition control | At -40 C, add fcs=0.4 to the model |
Abort moves to 0.274429720 V |
| Sidewall control | At -40 C, change only cjsw to 0 |
Completes to 5 us, with 5020 rows |
Setting CJSW to zero is a diagnostic control, not a proposed physical-model fix.
In src/spicelib/devices/dio/dioload.c at tag ngspice-46, the below-threshold sidewall charge uses the sidewall junction potential and grading coefficient. The above-threshold sidewall branch begins with:
deplchargeSW = czeroSW*here->DIOtF1 + ...
The apparent mismatch is that DIOtF1 is derived for the bottom junction, whereas the remainder of the sidewall expression uses sidewall quantities. In this model, PB != PHP and MJ != MJSW, so reusing the bottom-junction integration constant appears to leave the two sidewall-charge branches discontinuous.
For the reported run, the observed failure voltage matches this TLEVC=1 sidewall-threshold calculation:
PHP_T = 0.55456 - 0.0019629*(-40 - 27) = 0.6860743 V
FCS*PHP_T = 0.5*0.6860743 = 0.34303715 V
Here, PHP_T denotes the temperature-adjusted sidewall junction potential. The 27 C reference in this calculation reflects the implementation analyzed for the reported run; the netlist itself is reproduced unchanged above.
The corresponding bottom-junction F1 is approximately 0.423104172 V, whereas the sidewall continuity constant would be approximately 0.368004265 V. With this instance's temperature-adjusted sidewall capacitance, the difference predicts a charge jump of approximately 0.644584444 fC.
Additional equation-level diagnostics recorded in the original investigation found total charge changing from approximately 5.0450683 to 5.6896527 fC at this transition, while capacitance remained approximately 16.0882 fF. Replacing the sidewall charge with a continuous integral of the intended C(V) in a local diagnostic completed at both -40 C and 25 C. Those additional diagnostic files are not included in the attached four-case reproducer archive, and these observations are not a validation of a simulator C-source patch.
Could you check whether the sidewall continuation constant should be computed from its own temperature-adjusted potential, FCS, and grading coefficient, rather than reusing the bottom-junction constant?
A regression test with unequal bottom/sidewall parameters, more than one temperature, and a non-default FCS would help check both continuity of Q(V) and consistency of dQ/dV with the reported capacitance, as well as transient completion.
ngspice_sourceforge_reproducer.zip contains the baseline netlist, log, and trace, plus corresponding files in room_25C/, fcs_04/, and no_sidewall/. Each case can be run independently without the full PDK. It also contains this report and a short README.
Thanks for reporting this.
A fix is provided in pre-master-48.
A fix is provided in pre-master-48.