From 2a55f50192f7e99d3972fc44ee08e220c00fbb16 Mon Sep 17 00:00:00 2001 From: dwarning Date: Fri, 2 Apr 2021 17:17:41 +0200 Subject: [PATCH] First attempt for geometry scaled diode (level=3) --- src/spicelib/devices/dio/dio.c | 9 +++++++ src/spicelib/devices/dio/diodefs.h | 30 +++++++++++++++++++++++ src/spicelib/devices/dio/dioload.c | 3 ++- src/spicelib/devices/dio/diomask.c | 26 ++++++++++++++++++++ src/spicelib/devices/dio/diompar.c | 34 ++++++++++++++++++++++++++ src/spicelib/devices/dio/diosetup.c | 38 +++++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 1 deletion(-) diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index 1943e4ff6..3b292ad41 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -109,6 +109,15 @@ IFparm DIOmPTable[] = { /* model parameters */ IOP( "isr", DIO_MOD_ISR, IF_REAL, "Recombination saturation current"), IOP( "nr", DIO_MOD_NR, IF_REAL, "Recombination current emission coefficient"), + IOP( "lm", DIO_MOD_LM, IF_REAL, "Length of metal capacitor (level=3)"), + IOP( "lp", DIO_MOD_LP, IF_REAL, "Length of polysilicon capacitor (level=3)"), + IOP( "wm", DIO_MOD_WM, IF_REAL, "Width of metal capacitor (level=3)"), + IOP( "wp", DIO_MOD_WP, IF_REAL, "Width of polysilicon capacitor (level=3)"), + IOP( "xom", DIO_MOD_XOM, IF_REAL, "Thickness of the metal to bulk oxide (level=3)"), + IOP( "xoi", DIO_MOD_XOI, IF_REAL, "Thickness of the polysilicon to bulk oxide (level=3)"), + IOP( "xm", DIO_MOD_XM, IF_REAL, "Masking and etching effects in metal (level=3)"), + IOP( "xp", DIO_MOD_XP, IF_REAL, "Masking and etching effects in polysilicon (level=3)"), + IP( "d", DIO_MOD_D, IF_FLAG, "Diode model") }; diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index 77ac2f35f..46573f4ec 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -117,6 +117,9 @@ typedef struct sDIOinstance { double DIOjunctionSWCap; /* geometry adjusted junction sidewall capacitance */ double DIOtRecSatCur; /* temperature adjusted recombination saturation current */ + double DIOcmetal; /* parasitic metal overlap capacitance */ + double DIOcpoly; /* parasitic polysilicon overlap capacitance */ + /* * naming convention: * x = vdiode @@ -235,6 +238,15 @@ typedef struct sDIOmodel { /* model structure for a diode */ unsigned DIOrecSatCurGiven : 1; unsigned DIOrecEmissionCoeffGiven : 1; + unsigned DIOlengthMetalGiven : 1; /* Length of metal capacitor (level=3) */ + unsigned DIOlengthPolyGiven : 1; /* Length of polysilicon capacitor (level=3) */ + unsigned DIOwidthMetalGiven : 1; /* Width of metal capacitor (level=3) */ + unsigned DIOwidthPolyGiven : 1; /* Width of polysilicon capacitor (level=3) */ + unsigned DIOmetalOxideThickGiven : 1; /* Thickness of the metal to bulk oxide (level=3) */ + unsigned DIOpolyOxideThickGiven : 1; /* Thickness of the polysilicon to bulk oxide (level=3) */ + unsigned DIOmetalMaskOffsetGiven : 1; /* Masking and etching effects in metal (level=3)") */ + unsigned DIOpolyMaskOffsetGiven : 1; /* Masking and etching effects in polysilicon (level=3) */ + int DIOlevel; /* level selector */ double DIOsatCur; /* saturation current */ double DIOsatSWCur; /* Sidewall saturation current */ @@ -290,6 +302,15 @@ typedef struct sDIOmodel { /* model structure for a diode */ double DIOrecSatCur; /* Recombination saturation current */ double DIOrecEmissionCoeff; /* Recombination emission coefficient */ + double DIOlengthMetal; /* Length of metal capacitor (level=3) */ + double DIOlengthPoly; /* Length of polysilicon capacitor (level=3) */ + double DIOwidthMetal; /* Width of metal capacitor (level=3) */ + double DIOwidthPoly; /* Width of polysilicon capacitor (level=3) */ + double DIOmetalOxideThick; /* Thickness of the metal to bulk oxide (level=3) */ + double DIOpolyOxideThick; /* Thickness of the polysilicon to bulk oxide (level=3) */ + double DIOmetalMaskOffset; /* Masking and etching effects in metal (level=3)") */ + double DIOpolyMaskOffset; /* Masking and etching effects in polysilicon (level=3) */ + } DIOmodel; /* device parameters */ @@ -372,6 +393,15 @@ enum { DIO_MOD_BV_MAX, DIO_MOD_ISR, DIO_MOD_NR, + + DIO_MOD_LM, + DIO_MOD_LP, + DIO_MOD_WM, + DIO_MOD_WP, + DIO_MOD_XOM, + DIO_MOD_XOI, + DIO_MOD_XM, + DIO_MOD_XP, }; #include "dioext.h" diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index d9575bca0..90522415e 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -349,7 +349,8 @@ next1: if (model->DIOsatSWCurGiven) { /* sidewall current */ diffcap = here->DIOtTransitTime*gdb; diffcapSW = here->DIOtTransitTime*gdsw; - capd = diffcap + diffcapSW + deplcap + deplcapSW; + + capd = diffcap + diffcapSW + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly; here->DIOcap = capd; diff --git a/src/spicelib/devices/dio/diomask.c b/src/spicelib/devices/dio/diomask.c index 38d1d8601..96e7d138f 100644 --- a/src/spicelib/devices/dio/diomask.c +++ b/src/spicelib/devices/dio/diomask.c @@ -178,6 +178,32 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case DIO_MOD_NR: value->rValue = model->DIOrecEmissionCoeff; return(OK); + + case DIO_MOD_LM: + value->rValue = model->DIOlengthMetal; + return(OK); + case DIO_MOD_LP: + value->rValue = model->DIOlengthPoly; + return(OK); + case DIO_MOD_WM: + value->rValue = model->DIOwidthMetal; + return(OK); + case DIO_MOD_WP: + value->rValue = model->DIOwidthPoly; + return(OK); + case DIO_MOD_XOM: + value->rValue = model->DIOmetalOxideThick; + return(OK); + case DIO_MOD_XOI: + value->rValue = model->DIOpolyOxideThick; + return(OK); + case DIO_MOD_XM: + value->rValue = model->DIOmetalMaskOffset; + return(OK); + case DIO_MOD_XP: + value->rValue = model->DIOpolyMaskOffset; + return(OK); + default: return(E_BADPARM); } diff --git a/src/spicelib/devices/dio/diompar.c b/src/spicelib/devices/dio/diompar.c index 282423070..cdcdf7432 100644 --- a/src/spicelib/devices/dio/diompar.c +++ b/src/spicelib/devices/dio/diompar.c @@ -217,6 +217,40 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) model->DIOrecEmissionCoeff = value->rValue; model->DIOrecEmissionCoeffGiven = TRUE; break; + + case DIO_MOD_LM: + model->DIOlengthMetal = value->rValue; + model->DIOlengthMetalGiven = TRUE; + break; + case DIO_MOD_LP: + model->DIOlengthPoly = value->rValue; + model->DIOlengthPolyGiven = TRUE; + break; + case DIO_MOD_WM: + model->DIOwidthMetal = value->rValue; + model->DIOwidthMetalGiven = TRUE; + break; + case DIO_MOD_WP: + model->DIOwidthPoly = value->rValue; + model->DIOwidthPolyGiven = TRUE; + break; + case DIO_MOD_XOM: + model->DIOmetalOxideThick = value->rValue; + model->DIOmetalOxideThickGiven = TRUE; + break; + case DIO_MOD_XOI: + model->DIOpolyOxideThick = value->rValue; + model->DIOpolyOxideThickGiven = TRUE; + break; + case DIO_MOD_XM: + model->DIOmetalMaskOffset = value->rValue; + model->DIOmetalMaskOffsetGiven = TRUE; + break; + case DIO_MOD_XP: + model->DIOpolyMaskOffset = value->rValue; + model->DIOpolyMaskOffsetGiven = TRUE; + break; + case DIO_MOD_D: /* no action - we already know we are a diode, but this */ /* makes life easier for spice-2 like parsers */ diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index d956c4e03..1d8935009 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -15,15 +15,21 @@ Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 #include "diodefs.h" #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#include "ngspice/fteext.h" int DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) { + double scale; + DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; int error; CKTnode *tmp; + if (!cp_getvar("scale", CP_REAL, &scale, 0)) + scale = 1; + /* loop through all the diode models */ for( ; model != NULL; model = DIOnextModel(model)) { @@ -166,6 +172,31 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) model->DIOrecSatCur = 1e-14; } + if(!model->DIOlengthMetal) { + model->DIOlengthMetal = 0.0; + } + if(!model->DIOlengthPoly) { + model->DIOlengthPoly = 0.0; + } + if(!model->DIOwidthMetal) { + model->DIOwidthMetal = 0.0; + } + if(!model->DIOwidthPoly) { + model->DIOwidthPoly = 0.0; + } + if(!model->DIOmetalOxideThick) { + model->DIOmetalOxideThick = 10e3; + } + if(!model->DIOpolyOxideThick) { + model->DIOpolyOxideThick = 10e3; + } + if(!model->DIOmetalMaskOffset) { + model->DIOmetalMaskOffset = 0.0; + } + if(!model->DIOpolyMaskOffset) { + model->DIOpolyMaskOffset = 0.0; + } + /* loop through all the instances of the model */ for (here = DIOinstances(model); here != NULL ; here=DIOnextInstance(here)) { @@ -201,6 +232,13 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) here->DIOjunctionCap = model->DIOjunctionCap * here->DIOarea; here->DIOjunctionSWCap = model->DIOjunctionSWCap * here->DIOpj; + here->DIOcmetal = 3.9 * 8.854214871e-12 / model->DIOmetalOxideThick + * (model->DIOwidthMetal * scale + model->DIOmetalMaskOffset) + * (model->DIOlengthMetal * scale + model->DIOmetalMaskOffset); + here->DIOcpoly = 3.9 * 8.854214871e-12 / model->DIOpolyOxideThick + * (model->DIOwidthPoly * scale + model->DIOpolyMaskOffset) + * (model->DIOlengthPoly * scale + model->DIOpolyMaskOffset); + here->DIOstate = *states; *states += DIOnumStates; if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) ){