Add a generator for SEE (single event effects) pulses as a code model.

To be used like
aseegen1 NULL [%id(xcell.n1 m1) %id(xcell.n2 m2) %id(xcell.n1 m1) %id(xcell.n2 m2)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n tfall='tfall' trise='trise' let='let' cdepth='d')
see README.SEEgenerator for details
This commit is contained in:
Holger Vogt 2025-06-06 15:11:35 +02:00
parent 7f35cf4080
commit d3612562e1
20 changed files with 1185 additions and 0 deletions

173
README.SEEgenerator Normal file
View File

@ -0,0 +1,173 @@
SEE (single event effects) generator
The SEE generator generates current pulses, which resemble the
charge generation and flow causes by a penetrating particle.
How to use it:
Select LET and charge collection depth cdepth, define them as parameters.
Identify all nodes of a circuit netlist which are pn junctions,
and thus are sensitive to pulses.
Set up the SEEgenerator by adding for example
* charge collection depth (in µm)
.param d = 1
* LET (linear energy transfer) in MeV*cm²/mg
.param let = 12
aseegen1 NULL [%id(xcell.n1 m1) %id(xcell.n2 m2) %id(xcell.n1 m1) %id(xcell.n2 m2)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n let='let' cdepth='d')
to the netlist.
Each sensitive node from the (flattend) netlist may be added to assegen1, together with its
reference node, for example GND for NMOS, nwell potential for PMOS. This procedure is
currently to be done manually, an automated setup is in preparation.
After a transient simulation, plotting the data output versus a non-radiated device
may reveal the SEE influence.
Several examples are gieven in ./src/axamples/xspice/see: inverters, SRAM cell, opamp,
also as loop with varying LET to detect the threshold.
As literature please see for example
Ygor Quadros de Aguiar, Frédéric Wrobel. Jean-Luc Autran, Rubén García Alía
Single-Event Effects, from Space to Accelerator Environments
Springer 2025
Detailed description (will be added to the manual):
NAME_TABLE:
C_Function_Name: cm_seegen
Spice_Model_Name: seegen
Description: "single event effect generator"
PORT_TABLE:
Port_Name: ctrl out
Description: "control input" "output"
Direction: in out
Default_Type: v i
Allowed_Types: [v,vd,i,id] [i,id]
Vector: no yes
Vector_Bounds: - [1 -]
Null_Allowed: yes no
PARAMETER_TABLE:
Parameter_Name: tfall trise
Description: "pulse fall time" "pulse rise time"
Data_Type: real real
Default_Value: 500e-12 20e-12
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tdelay inull
Description: "pulse delay" "max current"
Data_Type: real real
Default_Value: 0 0
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tperiod ctrlthres
Description: "pulse repetition" "control voltage threshold"
Data_Type: real real
Default_Value: 0 0.5
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: let cdepth
Description: "lin energy transfer" "charge collection depth"
Data_Type: real real
Default_Value: 10 1
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: angle perlim
Description: "particle angle" "pulse repetition"
Data_Type: real boolean
Default_Value: 0 TRUE
Limits: [0 1.57079] -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
STATIC_VAR_TABLE:
Static_Var_Name: last_t_value
Data_Type: pointer
Vector: no
Description: "next pulse start time"
STATIC_VAR_TABLE:
Static_Var_Name: pulse_number
Data_Type: pointer
Vector: no
Description: "number of pulse"
STATIC_VAR_TABLE:
Static_Var_Name: last_ctrl
Data_Type: pointer
Vector: no
Description: "last control value"
Description
This code model generates "double exponentially" formed current pulses according to
i(t) = inull * (exp(-(t-tdelay)/tfall) - (exp(-(t-tdelay)/trise) for t > tdelay
i(t) = 0 for t < tdelay
with inull given as parameter input or (if not given), calculated as
inull = 1.035e-14 * let/cos(angle) * cdepth / (tfall - trise)
with data for silicon, cdepth in µm, let in MeV*cm²/mg, angle in radians.
Minimum is one pulse output (a node pair, or a single node with the other grounded).
Several output node pairs may be defined per code model instance. Parameter tperiod
may then be used to create pulses in sequence. Per default only one sequence is running,
with one pulse for each node.
Parameter perlim, set to FALSE, allows running and repeating the sequence until
the end of the simulation. The first pulse is issued in the first
node pair of the node list in the vector [], the second (after time tperiod has elapsed),
is injected by the second node (pair) of the list and so on. When the sequence is repeated,
again the output starts pulsing at port (node pair) number 1.
The control input ctrl (voltage or current) may be used
to start or repeat the whole sequence, depending on the circuit status. A rising voltage
at ctrl, when crossing the threshold given by ctrlthres, will initiate the sequence (including
tdelay and tperiod).
This model will work in transient analysis.
Example ngspice usage (with control)
aseegen1 ctrl [%id(n1 m1) %id(n2 m2) %id(n1 m1) %id(n2 m2)] seemod1
.model seemod1 seegen (tdelay = 8n tperiod=25n)
Example ngspice usage (without control, ctrl replaced by NULL, parameters as offered by default)
aseegen2 NULL [%id(n1 m1) %id(n5 n6) %id(n6 n7) %i(isingle) ] seemod2
.model seemod2 seegen (tdelay = 0 tperiod=0 ctrlthres=0.5 inull=0 tfall=500p trise=20p perlim=FALSE)

View File

@ -0,0 +1,33 @@
.title KiCad schematic
.include "cmos_sub.mod"
.include "seegen4.mod"
V1 Vcc 0 DC 3.3
XU1 VGP2 VGP4P8 Vbias VSN4N8 seegen4
XMN9 Vbias Vbias 0 0 NCH W=5u L=1.4u
V5 in+ 0 DC 1.65
R1 out in- 100k
R2 in in- 20k
V4 in 0 DC 1.65 SIN( 1.65 100m 1k 0 0 0 ) AC 1
XMN3 out Vbias 0 0 NCH W=17.4u L=1.4u
C2 out 0 2p
XMP2 out VGP2 Vcc Vcc PCH W=14.5u L=1.4u
C1 VGP2 out 1.2p
XMP4 VGP4P8 VGP4P8 Vcc Vcc PCH W=2.8u L=1.4u
I1 Vcc Vbias 12u
XMN4 VGP4P8 in- VSN4N8 0 NCH W=2.8u L=1.4u
XMN8 VGP2 in+ VSN4N8 0 NCH W=2.8u L=1.4u
XMN2 VSN4N8 Vbias 0 0 NCH W=5u L=1.4u
XMP8 VGP2 VGP4P8 Vcc Vcc PCH W=2.8u L=1.4u
.control
set xbrushwidth=2
tran 20n 2m
plot v(VGP4P8)
plot in out
ac dec 10 1 1Meg
plot db(out)
.endc
.end

View File

@ -0,0 +1,13 @@
* subcircuit model file
.include modelcard.nmos
.include modelcard.pmos
.subckt NCH D G S B W=1 L=1
MN1 D G S B N1 W={W} L={L} AS={3*L*W} AD={3*L*W} PS={6*L+W} AS={6*L+W}
.ends
.subckt PCH D G S B W=1 L=1
MP1 D G S B P1 W={W} L={L} AS={3*L*W} AD={3*L*W} PS={6*L+W} AS={6*L+W}
.ends

View File

@ -0,0 +1,46 @@
*model = bsim3v3
*Berkeley Spice Compatibility
*http://bsim.berkeley.edu/BSIM4/BSIM3/ftpv330.zip
* Lmin= .35 Lmax= 20 Wmin= .6 Wmax= 20
.model N1 NMOS
+Level= 8
+version=3.3.0
+Tnom=27.0
+Acnqsmod=1 elm=3
+Capmod=3
+Nch= 2.498E+17 Tox=9E-09 Xj=1.00000E-07
+Lint=9.36e-8 Wint=1.47e-7
+Lintnoi=1e-9
+Vth0= .6322 K1= .756 K2= -3.83e-2 K3= -2.612
+Dvt0= 2.812 Dvt1= 0.462 Dvt2=-9.17e-2
+Nlx= 3.52291E-08 W0= 1.163e-6
+K3b= 2.233
+Vsat= 86301.58 Ua= 6.47e-9 Ub= 4.23e-18 Uc=-4.706281E-11
+Rdsw= 650 U0= 388.3203 wr=1
+A0= .3496967 Ags=.1 B0=0.546 B1= 1
+Dwg = -6.0E-09 Dwb = -3.56E-09 Prwb = -.213
+Keta=-3.605872E-02 A1= 2.778747E-02 A2= .9
+Voff=-6.735529E-02 NFactor= 1.139926 Cit= 1.622527E-04
+Cdsc=-2.147181E-05
+Cdscb= 0 Dvt0w = 0 Dvt1w = 0 Dvt2w = 0
+Cdscd = 0 Prwg = 0
+Eta0= 1.0281729E-02 Etab=-5.042203E-03
+Dsub= .31871233
+Pclm= 1.114846 Pdiblc1= 2.45357E-03 Pdiblc2= 6.406289E-03
+Drout= .31871233 Pscbe1= 5000000 Pscbe2= 5E-09 Pdiblcb = -.234
+Pvag= 0 delta=0.01
+ Wl = 0 Ww = -1.420242E-09 Wwl = 0
+ Wln = 0 Wwn = .2613948 Ll = 1.300902E-10
+ Lw = 0 Lwl = 0 Lln = .316394
+ Lwn = 0
+kt1=-.3 kt2=-.051
+At= 22400
+Ute=-1.48
+Ua1= 3.31E-10 Ub1= 2.61E-19 Uc1= -3.42e-10
+Kt1l=0 Kt1=-0.1 Prt=764.3

View File

@ -0,0 +1,38 @@
*model = bsim3v3
*Berkeley Spice Compatibility
*http://bsim.berkeley.edu/BSIM4/BSIM3/ftpv330.zip
* Lmin= .35 Lmax= 20 Wmin= .6 Wmax= 20
.model P1 PMOS
+Level= 8
+version=3.3.0
+Tnom=27.0
+Acnqsmod=1 elm=3
+Nch= 3.533024E+17 Tox=9E-09 Xj=1.00000E-07
+Lint=6.23e-8 Wint=1.22e-7
+Lintnoi=1e-9
+Vth0=-.6732829 K1= .8362093 K2=-8.606622E-02 K3= 1.82
+Dvt0= 1.903801 Dvt1= .5333922 Dvt2=-.1862677
+Nlx= 1.28e-8 W0= 2.1e-6
+K3b= -0.24 Prwg=-0.001 Prwb=-0.323
+Vsat= 103503.2 Ua= 1.39995E-09 Ub= 1.e-19 Uc=-2.73e-11
+ Rdsw= 460 U0= 138.7609
+A0= .4716551 Ags=0.12
+Keta=-1.871516E-03 A1= .3417965 A2= 0.83
+Voff=-.074182 NFactor= 1.54389 Cit=-1.015667E-03
+Cdsc= 8.937517E-04
+Cdscb= 1.45e-4 Cdscd=1.04e-4
+ Dvt0w=0.232 Dvt1w=4.5e6 Dvt2w=-0.0023
+Eta0= 6.024776E-02 Etab=-4.64593E-03
+Dsub= .23222404
+Pclm= .989 Pdiblc1= 2.07418E-02 Pdiblc2= 1.33813E-3
+Drout= .3222404 Pscbe1= 118000 Pscbe2= 1E-09
+Pvag= 0
+kt1= -0.25 kt2= -0.032 prt=64.5
+At= 33000
+Ute= -1.5
+Ua1= 4.312e-9 Ub1= 6.65e-19 Uc1= 0
+Kt1l=0

View File

@ -0,0 +1,10 @@
* SEE generator model
.subckt seegen4 n1 n2 n3 n4
.param tochar = 2e-13
.param tfall = 500p trise=50p
.param Inull = 'tochar/(tfall-trise)'
* Eponential current source without control input
* only NMOS nodes with reference GND (substrate).
aseegen1 NULL [%i(n1) %i(n2) %i(n3) %i(n4)] seemod1
.model seemod1 seegen (tdelay = 0.62m tperiod=0.1m inull='Inull' perlim=FALSE)
.ends

View File

@ -0,0 +1,45 @@
* IHP Open PDK
* simple inverter
* Path to the PDK
*.include "D:\Spice_general\skywater-pdk\libraries\sky130_fd_pr\latest\models\corners/tt.spice"
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
*.include lib_out1.lib
.param vdd = 1.2
.param deltat=11n
* the voltage sources:
Vdd vd gnd DC 'vdd'
V1 in gnd pulse(0 'vdd' 0p 200p 100p 5n 10n)
* Eponential current source
Iset out 0 EXP(0 2.5m 'deltat' 10p 'deltat' 500p)
*Cset out 0 10f
Xnot1 in vdd vss out not1
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* simulation command:
.tran 100ps 50ns ; 0 10p
.options method=gear
.control
run
rusage
*set nolegend
set xbrushwidth=3
plot i(Vmeasvss) i(Vmeasvdd)
plot in out
.endc
.end

View File

@ -0,0 +1,61 @@
* IHP Open PDK
* simple SRAM cell, exponential current pulses
* Path to the PDK
*.include "D:\Spice_general\skywater-pdk\libraries\sky130_fd_pr\latest\models\corners/tt.spice"
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
*.include lib_out1.lib
.param vdd = 1.2
.param deltat=11n deltat2=27n
.param tochar = 1e-13
.param talpha = 500p tbeta=10p
.param Inull = 'tochar/(talpha-tbeta)'
* the voltage sources:
Vdd vd gnd DC 'vdd'
Vwl wl 0 0 PULSE 0 'vdd' 45n 1n 1n 7n 1
Vbl bl 0 'vdd'
Vbln bln 0 0
*V1 in gnd pulse(0 'vdd' 0p 200p 100p 5n 10n)
* Eponential current source without control input
aseegen1 NULL [%id(n1 m1) %id(n2 m2) %id(n1 m1) %id(n2 m2)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n inull='Inull')
Xnot1 n1 vdd vss n2 not1
Xnot2 n2 vdd vss n1 not1
xmo02 n2 wl bl vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
xmo01 n1 wl bln vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
Vm1 m1 0 0
Vm2 m2 0 0
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* starting condition for SRAM cell
.ic v(n2)=0 v(n1)='vdd'
* simulation command:
.tran 100ps 100ns ; 0 10p
.options method=gear
.control
run
rusage
*set nolegend
set xbrushwidth=3
plot i(Vmeasvss) i(Vmeasvdd)
plot n1 n2+2 wl+4 i(vm1)*10000+6 i(vm2)*10000+8
.endc
.end

View File

@ -0,0 +1,60 @@
* Simple SRAM cell in a subcircuit, double exponential current pulses
* control volate
* IHP Open PDK
* Path to the PDK
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
.param vdd = 1.2
.param deltat=11n deltat2=25n
.param tochar = 1e-13
.param talpha = 500p tbeta=20p
.param Inull = 'tochar/(talpha-tbeta)'
* the voltage sources:
Vdd vd gnd DC 'vdd'
Vwl wl 0 0 PULSE 0 'vdd' 50n 1n 1n 7n 1
Vbl bl 0 'vdd'
Vbln bln 0 0
Vctrl ctrl 0 pulse (0 1 10n 1n 1n 1 1)
* Exponential current source with control input
aseegen1 ctrl [%id(n1 m1) %id(n2 m2) %id(n1 m1) %id(n2 m2)] seemod1
.model seemod1 seegen (tdelay = 8n tperiod=25n)
Xnot1 n1 vdd vss n2 not1
Xnot2 n2 vdd vss n1 not1
xmo02 n2 wl bl vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
xmo01 n1 wl bln vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
Vm1 m1 0 0
Vm2 m2 0 0
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* starting condition for SRAM cell
.ic v(n2)=0 v(n1)='vdd'
* simulation command:
.tran 100ps 120ns
.options method=gear
.control
pre_osdi C:\Spice64\lib\ngspice\psp103_nqs.osdi
run
rusage
*set nolegend
set xbrushwidth=3
plot i(Vmeasvss) i(Vmeasvdd)
plot n1 n2+2 wl+4 i(vm1)*10000+6 i(vm2)*10000+8
.endc
.end

View File

@ -0,0 +1,69 @@
* Simple SRAM cell in a subcircuit, double exponential current pulses
* IHP Open PDK
* Path to the PDK
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
.param vdd = 1.2
.param deltat=11n deltat2=27n
*.param tochar = 1e-13 ; tochar dependency on LET not yet defined
.param tfall = 500p trise=20p ; tau in exponent for pulse
.param let = 11
.param cdepth = 0.9
*.param Inull = 'tochar/(tfall-trise)'
* the voltage sources:
Vdd vd gnd DC 'vdd'
Vwl wl 0 0 PULSE 0 'vdd' 45n 1n 1n 7n 1
Vbl1 bl1 0 'vdd'
Vbl2 bl2 0 0
**** SEE generator without control input, double exponential current sources
aseegen1 NULL [%id(xcell.n1 m1) %id(xcell.n2 m2) %id(xcell.n1 m1) %id(xcell.n2 m2)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n let='let' cdepth='cdepth' tfall='tfall' trise='trise')
* alternative syntax, if no current measurement required and reference nodes are GND
*aseegen1 NULL [%i(xcell.n1) %i(xcell.n2) %i(xcell.n1) %i(xcell.n2)] seemod1
**** the SRAM cell
Xcell bl1 bl2 wl vdd vss srcell
.subckt srcell bl1 bl2 wl vdd vss
Xnot1 n1 vdd vss n2 not1
Xnot2 n2 vdd vss n1 not1
xmo02 n2 wl bl1 vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
xmo01 n1 wl bl2 vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
.ends
**** Current measurements
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
Vm1 m1 0 0
Vm2 m2 0 0
**** Inverter cell
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* starting condition for SRAM cell
.ic v(xcell.n2)=0 v(xcell.n1)='vdd'
* simulation command:
.tran 100ps 120ns
*.options method=gear
.control
pre_osdi C:\Spice64\lib\ngspice\psp103_nqs.osdi
run
rusage
*set nolegend
set xbrushwidth=3
plot i(Vmeasvss) i(Vmeasvdd)
plot xcell.n1 xcell.n2+2 wl+4 i(vm1)*10000+6 i(vm2)*10000+8
.endc
.end

View File

@ -0,0 +1,81 @@
* Simple SRAM cell in a subcircuit, double exponential current pulses
* total charge is varied.
* IHP Open PDK
* Path to the PDK
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
.param vdd = 1.2
*.param tochar = 1e-13 ; tochar dependency on LET not yet defined
.param d = 1
.param let = 12
.param tochar = 1.035e-14 * let * d
.csparam let = 'let' ; send param value to .control section
.param tfall = 500p trise = 100p ; tau in exponent for pulse
.param Inull = 'tochar/(tfall-trise)'
* the voltage sources:
Vdd vd gnd DC 'vdd'
Vwl wl 0 0 PULSE 0 'vdd' 45n 1n 1n 7n 1
Vbl1 bl1 0 'vdd'
Vbl2 bl2 0 0
**** SEE generator without control input, double exponential current sources
aseegen1 NULL [%id(xcell.n1 m1) %id(xcell.n2 m2) %id(xcell.n1 m1) %id(xcell.n2 m2)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n tfall='tfall' trise='trise' let='let' cdepth='d')
* alternative syntax, if no current measurement required and reference nodes are GND
*aseegen1 NULL [%i(xcell.n1) %i(xcell.n2) %i(xcell.n1) %i(xcell.n2)] seemod1
**** the SRAM cell
Xcell bl1 bl2 wl vdd vss srcell
.subckt srcell bl1 bl2 wl vdd vss
Xnot1 n1 vdd vss n2 not1
Xnot2 n2 vdd vss n1 not1
xmo02 n2 wl bl1 vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
xmo01 n1 wl bl2 vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
.ends
**** Current measurements
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
Vm1 m1 0 0
Vm2 m2 0 0
**** Inverter cell
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* starting condition for SRAM cell
.ic v(xcell.n2)=0 v(xcell.n1)='vdd'
* simulation command:
.tran 100ps 120ns
*.options method=gear
.options noinit
.control
pre_osdi C:\Spice64\lib\ngspice\psp103_nqs.osdi
set xbrushwidth=3
let newlet = let
repeat 5
print newlet
run
plot xcell.n1 xcell.n2+2 wl+4 i(vm1)*10000+6 i(vm2)*10000+8 ylimit -1 10
let newlet = newlet - 1
alterparam let = $&newlet
reset
end
rusage
.endc
.end

View File

@ -0,0 +1,64 @@
* IHP Open PDK
* simple SRAM cell, exponential current pulses
* Path to the PDK
*.include "D:\Spice_general\skywater-pdk\libraries\sky130_fd_pr\latest\models\corners/tt.spice"
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
*.include lib_out1.lib
.param vdd = 1.2
.param deltat=11n deltat2=27n
.param tochar = 1e-13
.param talpha = 500p tbeta=10p
.param Inull = 'tochar/(talpha-tbeta)'
* the voltage sources:
Vdd vd gnd DC 'vdd'
Vwl wl 0 0 PULSE 0 'vdd' 45n 1n 1n 7n 1
Vbl bl 0 'vdd'
Vbln bln 0 0
*V1 in gnd pulse(0 'vdd' 0p 200p 100p 5n 10n)
* Eponential current source
Iset1 n1 m1 EXP(0 'Inull' 'deltat' 'tbeta' 'deltat' 'talpha')
Iset2 n2 m2 EXP(0 'Inull' 'deltat2' 'tbeta' 'deltat2' 'talpha')
Iset3 n1 m1 EXP(0 'Inull' 'deltat+50n' 'tbeta' 'deltat+50n' 'talpha')
Iset4 n2 m2 EXP(0 'Inull' 'deltat2+50n' 'tbeta' 'deltat2+50n' 'talpha')
*Cset out 0 10f
Xnot1 n1 vdd vss n2 not1
Xnot2 n2 vdd vss n1 not1
xmo02 n2 wl bl vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
xmo01 n1 wl bln vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
Vm1 m1 0 0
Vm2 m2 0 0
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* starting condition for SRAM cell
.ic v(n2)=0 v(n1)='vdd'
* simulation command:
.tran 100ps 100ns ; 0 10p
.options method=gear
.control
run
rusage
*set nolegend
set xbrushwidth=3
plot i(Vmeasvss) i(Vmeasvdd)
plot n1 n2+2 wl+4 i(vm1)*10000+6 i(vm2)*10000+8
.endc
.end

View File

@ -0,0 +1,48 @@
* IHP Open PDK
* simple inverter
* Path to the PDK
*.include "D:\Spice_general\skywater-pdk\libraries\sky130_fd_pr\latest\models\corners/tt.spice"
.lib "D:\Spice_general\IHP-Open-PDK\ihp-sg13g2\libs.tech\ngspice\models\cornerMOSlv.lib" mos_tt
*.include lib_out1.lib
.param vdd = 1.2
.param deltat=11n deltat2=27n
* the voltage sources:
Vdd vd gnd DC 'vdd'
V1 in gnd pulse(0 'vdd' 0p 200p 100p 5n 10n)
* Eponential current source
Iset1 out1 0 EXP(0 250u 'deltat' 10p 'deltat' 500p)
Iset2 out1 0 EXP(0 250u 'deltat2' 10p 'deltat2' 500p)
*Cset out 0 10f
Xnot1 in vdd vss out1 not1
Xnot2 out1 vdd vss out not1
Vmeasvss vss 0 0
Vmeasvdd vd vdd 0
.subckt not1 a vdd vss z
xm01 z a vdd vdd sg13_lv_pmos l=0.15u w=0.99u as=0.26235p ad=0.26235p ps=2.51u pd=2.51u
xm02 z a vss vss sg13_lv_nmos l=0.15u w=0.495u as=0.131175p ad=0.131175p ps=1.52u pd=1.52u
c3 a vss 0.384f
c2 z vss 0.576f
.ends
* simulation command:
.tran 100ps 50ns ; 0 10p
.options method=gear
.control
run
rusage
*set nolegend
set xbrushwidth=3
plot i(Vmeasvss) i(Vmeasvdd)
plot in out1+2 out+4
.endc
.end

View File

@ -0,0 +1,41 @@
* Repeat loop, double exponential current pulses
.param let = 10.5 cdepth = 1.2
.csparam let = 'let'
.param tfall = 500p trise = 20p ; tau in exponent for pulse
R1 n1 0 1e4
R2 n2 0 1e4
R3 n3 0 1e4
R4 n4 0 1e4
**** SEE generator without control input, double exponential current sources
aseegen1 NULL [%id(n1 0) %id(n2 0) %id(n3 0) %id(n4 0)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n let='let' cdepth='cdepth' trise='trise' tfall='tfall')
* alternative syntax, if no current measurement required and reference nodes are GND
*aseegen1 NULL [%i(n1) %i(n2) %i(n3) %i(n4)] seemod1
* simulation command:
.tran 100ps 120ns
*.options method=gear
.control
set xbrushwidth=3
*run
*plot n1 n2+2 n3+4 n4+6
let newlet = let
repeat 10
run
plot n1 n2+2 n3+4 n4+6 ylimit -3 7
let newlet = newlet - 0.5
alterparam let = $&newlet
reset
end
rusage
.endc
.end

View File

@ -0,0 +1,22 @@
Test of seegen code model
aseegen1 NULL [%id(n1 p1) %id(n2 p2) %id(n3 p3)] seemod1
.model seemod1 seegen (tdelay = 5n tperiod=4.5n)
Rsee1 n1 0 1
Vmeas1 p1 0 0
Rsee2 n2 0 1
Vmeas2 p2 0 0
Rsee3 n3 0 1
Vmeas3 p3 0 0
.control
tran 10p 35n
rusage time
set xbrushwidth=3
plot i(Vmeas1) i(Vmeas2)+200u i(Vmeas3)+400u
.endc
.end

View File

@ -0,0 +1,23 @@
SET pulse test
.param alpha = 100p beta = 500p deltat = 1n
* Arbitrary currnt source with expression
Bset1 1 0 I = ternary_fcn(TIME < 'deltat', 0, 2.5m * (exp(-(TIME-'deltat')/'alpha')-exp(-(TIME-'deltat')/'beta')))
R1 1 11 1
Vmeas 11 0 0
* Eponential current source
Iset 2 0 EXP(0 -2.5m 'deltat' 'alpha' 'deltat' 'beta')
R2 2 22 1
Vmeas2 22 0 0
.control
tran 1p 10n
set xbrushwidth=2
plot I(Vmeas)-I(Vmeas2)
plot I(Vmeas) I(Vmeas2)
.endc
.end

View File

@ -10,3 +10,4 @@ zener
memristor
sidiode
pswitch
seegenerator

View File

@ -0,0 +1,231 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
FILE seegenerator/cfunc.mod
Public Domain
Universty Duisburg-Essen
Duisburg, Germany
Project Flowspace
AUTHORS
19 May 2025 Holger Vogt
MODIFICATIONS
SUMMARY
This file contains the model-specific routines used to
functionally describe the see (single event effects) generator code model.
INTERFACES
FILE ROUTINE CALLED
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
===============================================================================*/
/*=== INCLUDE FILES ====================*/
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
static void
cm_seegen_callback(ARGS, Mif_Callback_Reason_t reason)
{
switch (reason) {
case MIF_CB_DESTROY: {
double *last_t_value = STATIC_VAR (last_t_value);
if (last_t_value)
free(last_t_value);
STATIC_VAR (last_t_value) = NULL;
int *pulse_number = STATIC_VAR (pulse_number);
if (pulse_number)
free(pulse_number);
STATIC_VAR (pulse_number) = NULL;
break;
double *last_ctrl = STATIC_VAR (last_ctrl);
if (last_ctrl)
free(last_ctrl);
STATIC_VAR (last_ctrl) = NULL;
}
}
}
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
FUNCTION void cm_seegen()
AUTHORS
19 May 2025 Holger Vogt
SUMMARY
This function implements the see generator code model.
INTERFACES
FILE ROUTINE CALLED
CMutil.c void cm_smooth_corner();
void cm_smooth_discontinuity();
void cm_climit_fcn()
RETURNED VALUE
Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
model source:
Ygor Quadros de Aguiar, Frédéric Wrobel. Jean-Luc Autran, Rubén García Alía
Single-Event Effects, from Space to Accelerator Environments
Springer 2025
==============================================================================*/
/*=== CM_SEEGEN ROUTINE ===*/
void cm_seegen(ARGS) /* structure holding parms,
inputs, outputs, etc. */
{
double tfall; /* pulse fall time */
double trise; /* pulse rise time */
double tdelay; /* delay until first pulse */
double inull; /* max. current of pulse */
double let; /* linear energy transfer */
double cdepth; /* charge collection depth */
double angle; /* particle entrance angle */
double tperiod; /* pulse repetition period */
double ctrlthres; /* control voltage threshold */
double ctrl; /* control input */
double out; /* output current */
double *last_t_value; /* static storage of next pulse time */
int *pulse_number; /* static storage of next pulse time */
double *last_ctrl; /* static storage of last ctrl value */
double tcurr = TIME; /* current simulation time */
if (ANALYSIS == MIF_AC) {
return;
}
/* Retrieve frequently used parameters... */
tfall = PARAM(tfall);
trise = PARAM(trise);
tdelay = PARAM(tdelay);
tperiod = PARAM(tperiod);
inull = PARAM(inull);
let = PARAM(let);
cdepth = PARAM(cdepth);
angle = PARAM(angle);
ctrlthres = PARAM(ctrlthres);
if (PORT_NULL(ctrl))
ctrl = 1;
else
ctrl = INPUT(ctrl);
if (INIT==1) {
/* Allocate storage for last_t_value */
STATIC_VAR(last_t_value) = (double *) malloc(sizeof(double));
last_t_value = (double *) STATIC_VAR(last_t_value);
*last_t_value = tdelay;
STATIC_VAR(pulse_number) = (int *) malloc(sizeof(int));
pulse_number = (int *) STATIC_VAR(pulse_number);
*pulse_number = 1;
STATIC_VAR(last_ctrl) = (double *) malloc(sizeof(double));
last_ctrl = (double *) STATIC_VAR(last_ctrl);
*last_ctrl = ctrl;
/* set breakpoints at first pulse start and pulse maximum times */
double tatmax = *last_t_value + tfall * trise * log(trise/tfall) / (trise - tfall);
cm_analog_set_perm_bkpt(*last_t_value);
cm_analog_set_perm_bkpt(tatmax);
}
else {
last_t_value = (double *) STATIC_VAR(last_t_value);
pulse_number = (int *) STATIC_VAR(pulse_number);
last_ctrl = (double *) STATIC_VAR(last_ctrl);
if (*last_ctrl < ctrlthres && ctrl >= ctrlthres) {
*last_t_value = *last_t_value + tcurr;
*last_ctrl = ctrl;
}
/* the double exponential current pulse function */
if (tcurr < *last_t_value)
out = 0;
else {
if (inull == 0) {
double LETeff = let/cos(angle);
double Qc = 1.035e-14 * LETeff * cdepth;
inull = Qc / (tfall - trise);
}
out = inull * (exp(-(tcurr-*last_t_value)/tfall) - exp(-(tcurr-*last_t_value)/trise));
}
if (tcurr > *last_t_value + tperiod * 0.9) {
/* return some info */
cm_message_printf("port name: out, node pair no.: %d, \nnode names: %s, %s, pulse time: %e",
*pulse_number, cm_get_node_name("out", *pulse_number - 1),
cm_get_neg_node_name("out", *pulse_number - 1), *last_t_value);
/* set the time for the next pulse */
*last_t_value = *last_t_value + tperiod;
/* set breakpoints at new pulse start and pulse maximum times */
double tatmax = *last_t_value + tfall * trise * log(trise/tfall) / (trise - tfall);
cm_analog_set_perm_bkpt(*last_t_value);
cm_analog_set_perm_bkpt(tatmax);
(*pulse_number)++;
if (*pulse_number > PORT_SIZE(out)) {
if (PARAM(perlim) == FALSE)
*pulse_number = 1;
else
*last_t_value = 1e12; /* stop any output */
}
}
if (*pulse_number - 1 < PORT_SIZE(out))
OUTPUT(out[*pulse_number - 1]) = out;
}
}

View File

@ -0,0 +1,120 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
Public Domain
Universty Duisburg-Essen
Duisburg, Germany
Project Flowspace
AUTHORS
Holger Vogt 19 May 2025
SUMMARY
This file contains the interface specification file for the
analog seegen code model.
===============================================================================*/
NAME_TABLE:
C_Function_Name: cm_seegen
Spice_Model_Name: seegen
Description: "single event effect generator"
PORT_TABLE:
Port_Name: ctrl out
Description: "control input" "output"
Direction: in out
Default_Type: v i
Allowed_Types: [v,vd,i,id] [i,id]
Vector: no yes
Vector_Bounds: - [1 -]
Null_Allowed: yes no
PARAMETER_TABLE:
Parameter_Name: tfall trise
Description: "pulse fall time" "pulse rise time"
Data_Type: real real
Default_Value: 500e-12 20e-12
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tdelay inull
Description: "pulse delay" "max current"
Data_Type: real real
Default_Value: 0 0
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tperiod ctrlthres
Description: "pulse repetition" "control voltage threshold"
Data_Type: real real
Default_Value: 0 0.5
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: let cdepth
Description: "lin energy transfer" "charge collection depth"
Data_Type: real real
Default_Value: 10 1
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: angle perlim
Description: "particle angle" "pulse repetition"
Data_Type: real boolean
Default_Value: 0 TRUE
Limits: [0 1.57079] -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
STATIC_VAR_TABLE:
Static_Var_Name: last_t_value
Data_Type: pointer
Vector: no
Description: "next pulse start time"
STATIC_VAR_TABLE:
Static_Var_Name: pulse_number
Data_Type: pointer
Vector: no
Description: "number of pulse"
STATIC_VAR_TABLE:
Static_Var_Name: last_ctrl
Data_Type: pointer
Vector: no
Description: "last control value"

View File

@ -248,6 +248,10 @@
<AdditionalIncludeDirectories>..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="icm\xtradev\memristor\memristor-ifspec.c" />
<ClCompile Include="icm\xtradev\seegenerator\seegenerator-cfunc.c">
<AdditionalIncludeDirectories>..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="icm\xtradev\seegenerator\seegenerator-ifspec.c" />
<ClCompile Include="..\..\src\xspice\icm\dlmain.c" />
</ItemGroup>
<ItemGroup>
@ -275,6 +279,8 @@
<None Include="..\..\src\xspice\icm\xtradev\zener\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\xtradev\memristor\cfunc.mod" />
<None Include="..\..\src\xspice\icm\xtradev\memristor\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\xtradev\seegenerator\cfunc.mod" />
<None Include="..\..\src\xspice\icm\xtradev\seegenerator\ifspec.ifs" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\include\ngspice\dstring.h" />