Handle the case when control voltages on and off are equal.

Update the linear switch: add the limits to resistance ron, roff
Update the log switch: correct the resistance calculation for
von < voff
Add some examples for the pswitch.
This commit is contained in:
Holger Vogt 2022-08-05 17:30:08 +02:00
parent b94ef139dd
commit c8ed9590b7
3 changed files with 180 additions and 42 deletions

View File

@ -0,0 +1,52 @@
* sw ring-oscillators
.control
destroy all
run
plot I(vmeasurea) I(vmeasureb) I(vmeasurec) I(vmeasured)
plot V(outa) V(outb) V(outc) V(outd)
rusage
.endc
.tran 3m 3
VDD VDD2 0 DC 3
Rla VDD2 outa 1k
Rlb VDD2 outb 1k
Rlc VDD2 outc 1k
Rld VDD2 outd 1k
VMEASUREa DGNDa 0 dc 0
VMEASUREb DGNDb 0 dc 0
VMEASUREc DGNDc 0 dc 0
VMEASUREd DGNDd 0 dc 0
Vin in 0 pulse ( 0 3 0 3 3 10 10 )
xsa in outa DGNDa switcha
xsb in outb DGNDb switchb
xsc in outc DGNDc switchc
xsd in outd DGNDd switchd
.subckt switcha In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=false cntl_on=1.5 cntl_off=2.5 r_on=1k r_off=2g)
.ends
.subckt switchb In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=false cntl_on=1.5 cntl_off=2.5 r_on=1k r_off=2k)
.ends
.subckt switchc In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=false cntl_on=2.5 cntl_off=1.5 r_on=1k r_off=2g)
.ends
.subckt switchd In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=false cntl_on=2.5 cntl_off=1.5 r_on=1k r_off=2k)
.ends
.end

View File

@ -0,0 +1,52 @@
* sw ring-oscillators
.control
destroy all
run
plot I(vmeasurea) I(vmeasureb) I(vmeasurec) I(vmeasured)
plot V(outa) V(outb) V(outc) V(outd)
rusage
.endc
.tran 3m 3
VDD VDD2 0 DC 3
Rla VDD2 outa 1k
Rlb VDD2 outb 1k
Rlc VDD2 outc 1k
Rld VDD2 outd 1k
VMEASUREa DGNDa 0 dc 0
VMEASUREb DGNDb 0 dc 0
VMEASUREc DGNDc 0 dc 0
VMEASUREd DGNDd 0 dc 0
Vin in 0 pulse ( 0 3 0 3 3 10 10 )
xsa in outa DGNDa switcha
xsb in outb DGNDb switchb
xsc in outc DGNDc switchc
xsd in outd DGNDd switchd
.subckt switcha In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=true cntl_on=1.5 cntl_off=2.5 r_on=1k r_off=2g)
.ends
.subckt switchb In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=true cntl_on=1.5 cntl_off=2.5 r_on=1k r_off=2k)
.ends
.subckt switchc In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=true cntl_on=2.5 cntl_off=1.5 r_on=1k r_off=2g)
.ends
.subckt switchd In Out DGND
a.xx17.asn %gd in DGND %gd out DGND aswswitch
.model aswswitch pswitch( log=true cntl_on=2.5 cntl_off=1.5 r_on=1k r_off=2k)
.ends
.end

View File

@ -71,6 +71,8 @@ typedef struct {
the resistance of the switch when the
controlling voltage is between cntl_on
and cntl_of */
double cntl_on; /* voltage above which switch come on */
double cntl_off; /* voltage below the switch has resistance roff */
double c1; /* some constants */
double c2;
double c3;
@ -167,8 +169,6 @@ void cm_pswitch(ARGS) /* structure holding parms,
/* Retrieve frequently used parameters... */
cntl_on = PARAM(cntl_on);
cntl_off = PARAM(cntl_off);
r_on = PARAM(r_on);
r_off = PARAM(r_off);
r_cntl_in = PARAM(r_cntl_in);
@ -180,9 +180,11 @@ void cm_pswitch(ARGS) /* structure holding parms,
if(INIT == 1) { /* first time through, allocate memory, set static parameters */
char *cntl_error = "\n*****ERROR*****\nPSWITCH: CONTROL voltage delta less than 1.0e-12\n";
cntl_on = PARAM(cntl_on);
cntl_off = PARAM(cntl_off);
if( (fabs(cntl_on - cntl_off) < 1.0e-12) ) {
cm_message_send(cntl_error);
return;
cntl_on += 0.001;
cntl_off -= 0.001;
}
CALLBACK = cm_pswitch_callback;
@ -191,6 +193,9 @@ void cm_pswitch(ARGS) /* structure holding parms,
STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t ));
loc = STATIC_VAR (locdata);
loc->cntl_on = cntl_on;
loc->cntl_off = cntl_off;
if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */
if (cntl_on > cntl_off)
{
@ -219,6 +224,8 @@ void cm_pswitch(ARGS) /* structure holding parms,
loc = STATIC_VAR (locdata);
cntl_on = loc->cntl_on;
cntl_off = loc->cntl_off;
if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */
logmean = loc->logmean;
logratio = loc->logratio;
@ -228,7 +235,7 @@ void cm_pswitch(ARGS) /* structure holding parms,
double inmean;// = INPUT(cntl_in) - cntl_mean;
int outOfLimit = 0;
if (cntl_on > cntl_off) {
inmean = ((INPUT(cntl_in) - PARAM(cntl_off)) / (PARAM(cntl_on) - PARAM(cntl_off))) - cntl_mean;
inmean = (INPUT(cntl_in) - cntl_off) / (cntl_on - cntl_off) - cntl_mean;
if (INPUT(cntl_in) > cntl_on) {
r = r_on;
outOfLimit = 1;
@ -242,7 +249,7 @@ void cm_pswitch(ARGS) /* structure holding parms,
if(r<r_on) r=r_on;/* minimum resistance limiter */
}
} else {
inmean = ((PARAM(cntl_on) - INPUT(cntl_in)) / (PARAM(cntl_off) - PARAM(cntl_on))) - cntl_mean;
inmean = (cntl_on - INPUT(cntl_in)) / (cntl_on - cntl_off) - cntl_mean;
if (INPUT(cntl_in) < cntl_on) {
r = r_on;
outOfLimit = 1;
@ -267,11 +274,38 @@ void cm_pswitch(ARGS) /* structure holding parms,
else { /* Linear Variation in 'R' */
intermediate = loc->intermediate;
cntl_diff = loc->cntl_diff;
if (cntl_diff >=0) {
if (INPUT(cntl_in) < cntl_off) {
r = r_off;
pi_pcntl = 0;
}
else if (INPUT(cntl_in) > cntl_on) {
r = r_on;
pi_pcntl = 0;
}
else {
r = INPUT(cntl_in) * intermediate + ((r_off*cntl_on -
r_on*cntl_off) / cntl_diff);
pi_pcntl = -intermediate * INPUT(out) / (r*r);
}
}
else {
if (INPUT(cntl_in) > cntl_off) {
r = r_off;
pi_pcntl = 0;
}
else if (INPUT(cntl_in) < cntl_on) {
r = r_on;
pi_pcntl = 0;
}
else {
r = INPUT(cntl_in) * intermediate + ((r_off*cntl_on -
r_on*cntl_off) / cntl_diff);
pi_pcntl = -intermediate * INPUT(out) / (r*r);
}
}
if(r<=1.0e-9) r=1.0e-9;/* minimum resistance limiter */
pi_pvout = 1.0 / r;
pi_pcntl = -intermediate * INPUT(out) / (r*r);
}
if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */