selectable flicker noise models for mos1...3

This commit is contained in:
dwarning 2024-01-23 14:55:08 +01:00
parent 2a6db71726
commit 1381d71cb1
18 changed files with 162 additions and 24 deletions

View File

@ -148,7 +148,8 @@ IFparm MOS1mPTable[] = { /* model parameters */
IOP("nss", MOS1_MOD_NSS, IF_REAL ,"Surface state density"),
IOP("tnom", MOS1_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"),
IOP("kf", MOS1_MOD_KF, IF_REAL ,"Flicker noise coefficient"),
IOP("af", MOS1_MOD_AF, IF_REAL ,"Flicker noise exponent")
IOP("af", MOS1_MOD_AF, IF_REAL ,"Flicker noise exponent"),
IOP("nlev", MOS1_MOD_NLEV, IF_INTEGER ,"Noise model selection")
};
char *MOS1names[] = {

View File

@ -383,6 +383,7 @@ typedef struct sMOS1model { /* model structure for a resistor */
double MOS1surfaceMobility; /* input - use tSurfMob */
double MOS1fNcoef;
double MOS1fNexp;
int MOS1nlev;
unsigned MOS1typeGiven :1;
unsigned MOS1latDiffGiven :1;
@ -415,6 +416,7 @@ typedef struct sMOS1model { /* model structure for a resistor */
unsigned MOS1tnomGiven :1;
unsigned MOS1fNcoefGiven :1;
unsigned MOS1fNexpGiven :1;
unsigned MOS1nlevGiven :1;
} MOS1model;
@ -483,6 +485,7 @@ enum {
MOS1_MOD_TNOM,
MOS1_MOD_KF,
MOS1_MOD_AF,
MOS1_MOD_NLEV,
MOS1_MOD_TYPE,
};

View File

@ -105,6 +105,9 @@ MOS1mAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case MOS1_MOD_NSS:
value->rValue = model->MOS1surfaceStateDensity;
return(OK);
case MOS1_MOD_NLEV:
value->iValue = model->MOS1nlev;
return(OK);
case MOS1_MOD_TYPE:
if (model->MOS1type > 0)
value->sValue = "nmos";

View File

@ -147,6 +147,10 @@ MOS1mParam(int param, IFvalue *value, GENmodel *inModel)
model->MOS1fNexp = value->rValue;
model->MOS1fNexpGiven = TRUE;
break;
case MOS1_MOD_NLEV:
model->MOS1nlev = value->iValue;
model->MOS1nlevGiven = TRUE;
break;
default:
return(E_BADPARM);
}

View File

@ -10,6 +10,7 @@ Modified: 2000 AlansFixes
#include "ngspice/iferrmsg.h"
#include "ngspice/noisedef.h"
#include "ngspice/suffix.h"
#include "ngspice/compatmode.h"
/*
* MOS1noise (mode, operation, firstModel, ckt, data, OnDens)
@ -108,13 +109,44 @@ MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
NevalSrc( & noizDens[MOS1FLNOIZ], NULL, ckt,
N_GAIN, inst -> MOS1dNodePrime, inst -> MOS1sNodePrime,
(double) 0.0);
noizDens[MOS1FLNOIZ] *= model -> MOS1fNcoef *
exp(model -> MOS1fNexp *
log(MAX(fabs(inst -> MOS1cd), N_MINLOG))) /
(data -> freq *
inst -> MOS1w *
(inst -> MOS1l - 2 * model -> MOS1latDiff) *
coxSquared);
if (newcompat.s3) {
noizDens[MOS1FLNOIZ] *= model -> MOS1fNcoef *
exp(model -> MOS1fNexp *
log(MAX(fabs(inst -> MOS1cd), N_MINLOG))) /
(data -> freq *
inst -> MOS1w *
(inst -> MOS1l - 2 * model -> MOS1latDiff) *
coxSquared);
} else {
switch (model -> MOS1nlev) {
case 0:
noizDens[MOS1FLNOIZ] *= model -> MOS1fNcoef *
exp(model -> MOS1fNexp *
log(MAX(fabs(inst -> MOS1cd), N_MINLOG))) /
(data -> freq *
(inst -> MOS1l - 2 * model -> MOS1latDiff) *
(inst -> MOS1l - 2 * model -> MOS1latDiff) *
sqrt(coxSquared));
break;
case 1:
noizDens[MOS1FLNOIZ] *= model -> MOS1fNcoef *
exp(model -> MOS1fNexp *
log(MAX(fabs(inst -> MOS1cd), N_MINLOG))) /
(data -> freq *
inst -> MOS1w *
(inst -> MOS1l - 2 * model -> MOS1latDiff) *
sqrt(coxSquared));
break;
case 2: case 3:
noizDens[MOS1FLNOIZ] *= model -> MOS1fNcoef *
inst -> MOS1gm * inst -> MOS1gm /
(pow(data -> freq, model -> MOS1fNexp) *
inst -> MOS1w *
(inst -> MOS1l - 2 * model -> MOS1latDiff) *
sqrt(coxSquared));
break;
}
}
lnNdens[MOS1FLNOIZ] =
log(MAX(noizDens[MOS1FLNOIZ], N_MINLOG));

View File

@ -87,6 +87,9 @@ MOS1setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
if(!model->MOS1fNexpGiven) {
model->MOS1fNexp = 1;
}
if(!model->MOS1nlevGiven) {
model->MOS1nlev = 2;
}
/* loop through all the instances of the model */
for (here = MOS1instances(model); here != NULL ;

View File

@ -156,7 +156,8 @@ IFparm MOS2mPTable[] = { /* model parameters */
IOP("nfs", MOS2_MOD_NFS, IF_REAL ,"Fast surface state density"),
IOPU("tnom", MOS2_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"),
IOP("kf", MOS2_MOD_KF, IF_REAL ,"Flicker noise coefficient"),
IOP("af", MOS2_MOD_AF, IF_REAL ,"Flicker noise exponent")
IOP("af", MOS2_MOD_AF, IF_REAL ,"Flicker noise exponent"),
IOP("nlev", MOS2_MOD_NLEV, IF_INTEGER ,"Noise model selection")
};
char *MOS2names[] = {

View File

@ -390,6 +390,7 @@ typedef struct sMOS2model { /* model structure for a resistor */
double MOS2surfaceMobility;
double MOS2fNcoef;
double MOS2fNexp;
int MOS2nlev;
double MOS2narrowFactor; /* delta */
double MOS2critFieldExp; /* uexp */
@ -437,6 +438,7 @@ typedef struct sMOS2model { /* model structure for a resistor */
unsigned MOS2channelChargeGiven :1; /* neff */
unsigned MOS2fNcoefGiven :1;
unsigned MOS2fNexpGiven :1;
unsigned MOS2nlevGiven :1;
} MOS2model;
@ -574,6 +576,7 @@ enum {
enum {
MOS2_MOD_KF = 139,
MOS2_MOD_AF,
MOS2_MOD_NLEV,
MOS2_MOD_TYPE,
};

View File

@ -130,6 +130,9 @@ MOS2mAsk(CKTcircuit *ckt, GENmodel *inModel, int param,
case MOS2_MOD_AF:
value->rValue = model->MOS2fNexp;
break;
case MOS2_MOD_NLEV:
value->iValue = model->MOS2nlev;
break;
case MOS2_MOD_TYPE:
if (model->MOS2type > 0)
value->sValue = "nmos";

View File

@ -178,6 +178,10 @@ MOS2mParam(int param, IFvalue *value, GENmodel *inModel)
model->MOS2fNexp = value->rValue;
model->MOS2fNexpGiven = TRUE;
break;
case MOS2_MOD_NLEV:
model->MOS2nlev = value->iValue;
model->MOS2nlevGiven = TRUE;
break;
default:
return(E_BADPARM);
}

View File

@ -10,6 +10,7 @@ Modified: 2000 AlansFixes
#include "ngspice/iferrmsg.h"
#include "ngspice/noisedef.h"
#include "ngspice/suffix.h"
#include "ngspice/compatmode.h"
/*
* MOS2noise (mode, operation, firstModel, ckt, data, OnDens)
@ -97,13 +98,44 @@ MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
NevalSrc( & noizDens[MOS2FLNOIZ], NULL, ckt,
N_GAIN, inst -> MOS2dNodePrime, inst -> MOS2sNodePrime,
(double) 0.0);
noizDens[MOS2FLNOIZ] *= model -> MOS2fNcoef *
exp(model -> MOS2fNexp *
log(MAX(fabs(inst -> MOS2cd), N_MINLOG))) /
(data -> freq *
inst -> MOS2w *
(inst -> MOS2l - 2 * model -> MOS2latDiff) *
model -> MOS2oxideCapFactor * model -> MOS2oxideCapFactor);
if (newcompat.s3) {
noizDens[MOS2FLNOIZ] *= model -> MOS2fNcoef *
exp(model -> MOS2fNexp *
log(MAX(fabs(inst -> MOS2cd), N_MINLOG))) /
(data -> freq *
inst -> MOS2w *
(inst -> MOS2l - 2 * model -> MOS2latDiff) *
model -> MOS2oxideCapFactor * model -> MOS2oxideCapFactor);
} else {
switch (model -> MOS2nlev) {
case 0:
noizDens[MOS2FLNOIZ] *= model -> MOS2fNcoef *
exp(model -> MOS2fNexp *
log(MAX(fabs(inst -> MOS2cd), N_MINLOG))) /
(data -> freq *
(inst -> MOS2l - 2 * model -> MOS2latDiff) *
(inst -> MOS2l - 2 * model -> MOS2latDiff) *
model -> MOS2oxideCapFactor);
break;
case 1:
noizDens[MOS2FLNOIZ] *= model -> MOS2fNcoef *
exp(model -> MOS2fNexp *
log(MAX(fabs(inst -> MOS2cd), N_MINLOG))) /
(data -> freq *
inst -> MOS2w *
(inst -> MOS2l - 2 * model -> MOS2latDiff) *
model -> MOS2oxideCapFactor);
break;
case 2: case 3:
noizDens[MOS2FLNOIZ] *= model -> MOS2fNcoef *
inst -> MOS2gm * inst -> MOS2gm /
(pow(data -> freq, model -> MOS2fNexp) *
inst -> MOS2w *
(inst -> MOS2l - 2 * model -> MOS2latDiff) *
model -> MOS2oxideCapFactor);
break;
}
}
lnNdens[MOS2FLNOIZ] =
log(MAX(noizDens[MOS2FLNOIZ], N_MINLOG));

View File

@ -116,6 +116,9 @@ MOS2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
if(!model->MOS2fNexpGiven) {
model->MOS2fNexp = 1;
}
if(!model->MOS2nlevGiven) {
model->MOS2nlev = 2;
}
/* loop through all the instances of the model */
for (here = MOS2instances(model); here != NULL ;

View File

@ -156,7 +156,8 @@ IFparm MOS3mPTable[] = { /* model parameters */
IOP("kappa", MOS3_MOD_KAPPA, IF_REAL ,"Kappa"),
IOPU("tnom", MOS3_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"),
IOP("kf", MOS3_MOD_KF, IF_REAL ,"Flicker noise coefficient"),
IOP("af", MOS3_MOD_AF, IF_REAL ,"Flicker noise exponent")
IOP("af", MOS3_MOD_AF, IF_REAL ,"Flicker noise exponent"),
IOP("nlev", MOS3_MOD_NLEV, IF_INTEGER ,"Noise model selection")
};
char *MOS3names[] = {

View File

@ -400,6 +400,7 @@ typedef struct sMOS3model { /* model structure for a resistor */
double MOS3kappa; /* kappa */
double MOS3fNcoef;
double MOS3fNexp;
int MOS3nlev;
unsigned MOS3typeGiven :1;
unsigned MOS3latDiffGiven :1;
@ -442,6 +443,7 @@ typedef struct sMOS3model { /* model structure for a resistor */
unsigned MOS3tnomGiven :1; /* Tnom was given? */
unsigned MOS3fNcoefGiven :1;
unsigned MOS3fNexpGiven :1;
unsigned MOS3nlevGiven :1;
} MOS3model;
@ -580,6 +582,7 @@ enum {
MOS3_MOD_TNOM,
MOS3_MOD_KF,
MOS3_MOD_AF,
MOS3_MOD_NLEV,
MOS3_MOD_TYPE,
MOS3_MOD_XL,
MOS3_MOD_WD,

View File

@ -154,6 +154,9 @@ MOS3mAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case MOS3_MOD_AF:
value->rValue = here->MOS3fNexp;
return(OK);
case MOS3_MOD_NLEV:
value->iValue = here->MOS3nlev;
return(OK);
case MOS3_MOD_TYPE:
if (here->MOS3type > 0)
value->sValue = "nmos";

View File

@ -191,6 +191,10 @@ MOS3mParam(int param, IFvalue *value, GENmodel *inModel)
model->MOS3fNexp = value->rValue;
model->MOS3fNexpGiven = TRUE;
break;
case MOS3_MOD_NLEV:
model->MOS3nlev = value->iValue;
model->MOS3nlevGiven = TRUE;
break;
default:
return(E_BADPARM);
}

View File

@ -10,6 +10,7 @@ Modified: 2000 AlansFixes
#include "ngspice/iferrmsg.h"
#include "ngspice/noisedef.h"
#include "ngspice/suffix.h"
#include "ngspice/compatmode.h"
/*
* MOS3noise (mode, operation, firstModel, ckt, data, OnDens)
@ -97,13 +98,44 @@ MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
NevalSrc( & noizDens[MOS3FLNOIZ], NULL, ckt,
N_GAIN, inst -> MOS3dNodePrime, inst -> MOS3sNodePrime,
(double) 0.0);
noizDens[MOS3FLNOIZ] *= model -> MOS3fNcoef *
exp(model -> MOS3fNexp *
log(MAX(fabs(inst -> MOS3cd), N_MINLOG))) /
(data -> freq *
(inst -> MOS3w - 2 * model -> MOS3widthNarrow) *
(inst -> MOS3l - 2 * model -> MOS3latDiff) *
model -> MOS3oxideCapFactor * model -> MOS3oxideCapFactor);
if (newcompat.s3) {
noizDens[MOS3FLNOIZ] *= model -> MOS3fNcoef *
exp(model -> MOS3fNexp *
log(MAX(fabs(inst -> MOS3cd), N_MINLOG))) /
(data -> freq *
(inst -> MOS3w - 2 * model -> MOS3widthNarrow) *
(inst -> MOS3l - 2 * model -> MOS3latDiff) *
model -> MOS3oxideCapFactor * model -> MOS3oxideCapFactor);
} else {
switch (model -> MOS3nlev) {
case 0:
noizDens[MOS3FLNOIZ] *= model -> MOS3fNcoef *
exp(model -> MOS3fNexp *
log(MAX(fabs(inst -> MOS3cd), N_MINLOG))) /
(data -> freq *
(inst -> MOS3l - 2 * model -> MOS3latDiff) *
(inst -> MOS3l - 2 * model -> MOS3latDiff) *
model -> MOS3oxideCapFactor);
break;
case 1:
noizDens[MOS3FLNOIZ] *= model -> MOS3fNcoef *
exp(model -> MOS3fNexp *
log(MAX(fabs(inst -> MOS3cd), N_MINLOG))) /
(data -> freq *
(inst -> MOS3w - 2 * model -> MOS3widthNarrow) *
(inst -> MOS3l - 2 * model -> MOS3latDiff) *
model -> MOS3oxideCapFactor);
break;
case 2: case 3:
noizDens[MOS3FLNOIZ] *= model -> MOS3fNcoef *
inst -> MOS3gm * inst -> MOS3gm /
(pow(data -> freq, model -> MOS3fNexp) *
(inst -> MOS3w - 2 * model -> MOS3widthNarrow) *
(inst -> MOS3l - 2 * model -> MOS3latDiff) *
model -> MOS3oxideCapFactor);
break;
}
}
lnNdens[MOS3FLNOIZ] =
log(MAX(noizDens[MOS3FLNOIZ], N_MINLOG));

View File

@ -139,6 +139,9 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
if(!model->MOS3fNexpGiven) {
model->MOS3fNexp = 1;
}
if(!model->MOS3nlevGiven) {
model->MOS3nlev = 2;
}
/* loop through all the instances of the model */
for (here = MOS3instances(model); here != NULL ;