Fix the NAND and NOR variants of XSPICE code model multi_input_pwl
and add an example of its use with the E-source NAND variant.
This commit is contained in:
parent
3a260fd4d9
commit
576f218945
|
|
@ -1,4 +1,4 @@
|
|||
Compare four different 4-bit full adders,
|
||||
Compare five different 4-bit full adders,
|
||||
made of NAND gates
|
||||
Simulating for 6400ns
|
||||
|
||||
|
|
@ -21,3 +21,9 @@ Fully digital, event node based NAND gates
|
|||
digital plotting into vcd file, display with gtkwave
|
||||
Simulation time 0.27s
|
||||
|
||||
adder_esource
|
||||
Uses the NAND variant of the E-type behavioral voltage source.
|
||||
|
||||
There are further variations of adder_Xspice in directory
|
||||
examples/digital/auto_bridge.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
ADDER - 4 BIT BINARY ADDER USING E-SOURCE AND GATES
|
||||
* behavioral gate description
|
||||
|
||||
*** SUBCIRCUIT DEFINITION
|
||||
|
||||
.SUBCKT 74HC00 in1 in2 out NVCC NVGND vcc1={vcc} tripdt1={tripdt}
|
||||
.param Rout={60*4.0/(vcc1-0.5)} ; standard output driver
|
||||
E1 out20 0 nand(2) in1 0 in2 0 ({vcc / 3}, 0) ({2 * vcc / 3}, {vcc})
|
||||
Rout out20 out {Rout}
|
||||
.ends
|
||||
|
||||
.param vcc=3 tripdt=6n
|
||||
|
||||
.include ../adder_common.inc
|
||||
|
||||
.END
|
||||
|
|
@ -174,33 +174,81 @@ get_output( ARGS, double x )
|
|||
return result;
|
||||
}
|
||||
|
||||
static double
|
||||
get_reverse_output( ARGS, double x )
|
||||
{
|
||||
int size = PARAM_SIZE(x);
|
||||
double result = 0;
|
||||
double slope = 0;
|
||||
int i;
|
||||
|
||||
/* check if x beyond specified limits */
|
||||
if ( x <= PARAM(x[0]) ) return PARAM(y[size-1]);
|
||||
if ( x >= PARAM(x[size-1]) ) return PARAM(y[0]);
|
||||
|
||||
for ( i = 1; i < size; i++ )
|
||||
if ( x > PARAM(x[i-1]) && x <= PARAM(x[i]) )
|
||||
{
|
||||
result = PARAM(y[size - i - 1]) + slope * (x - PARAM(x[i - 1]));
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
cm_multi_input_pwl(ARGS)
|
||||
{
|
||||
const char* model = ( PARAM_NULL(model) == 1 ) ? "and" : PARAM(model);
|
||||
const char* model = PARAM(model);
|
||||
double output;
|
||||
|
||||
if ( ANALYSIS == TRANSIENT || ANALYSIS == DC )
|
||||
{
|
||||
if ( strcmp( model, "and" ) != 0 && strcmp( model, "or" ) != 0 &&
|
||||
strcmp( model, "nand" ) != 0 && strcmp( model, "nor" ) != 0 )
|
||||
{
|
||||
fprintf( stderr, "ERROR(cm_multi_input_pwl): unknown gate model type '%s'; expecting 'and|or|nand|nor'.\n", model );
|
||||
if (INIT) {
|
||||
int type;
|
||||
|
||||
if (!strcmp(model, "and"))
|
||||
type = 0;
|
||||
else if (!strcmp(model, "nand"))
|
||||
type = 1;
|
||||
else if (!strcmp(model, "or"))
|
||||
type = 2;
|
||||
else if (!strcmp(model, "nor"))
|
||||
type = 3;
|
||||
else {
|
||||
fprintf(stderr, "ERROR(cm_multi_input_pwl): unknown gate model type "
|
||||
"'%s'; expecting 'and|or|nand|nor'.\n", model );
|
||||
exit(-1);
|
||||
}
|
||||
if ( PARAM_SIZE(x) != PARAM_SIZE(y) )
|
||||
{
|
||||
fprintf( stderr, "ERROR(cm_multi_input_pwl): 'x' and 'y' input vectors are not the same size!\n" );
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
STATIC_VAR(type) = type;
|
||||
if ( PARAM_SIZE(x) != PARAM_SIZE(y) ) {
|
||||
fprintf(stderr, "ERROR(cm_multi_input_pwl): 'x' and 'y' input vectors are not the same size!\n" );
|
||||
if (PARAM_SIZE(x) > PARAM_SIZE(y))
|
||||
PARAM_SIZE(x) = PARAM_SIZE(y);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ANALYSIS == TRANSIENT || ANALYSIS == DC ) {
|
||||
/*
|
||||
Iterate through each input and find output value
|
||||
and/nand: controlling input is chosen on the basis of the smallest value
|
||||
or/nor: controlling input is chosen on the basis of the largest value
|
||||
*/
|
||||
if (strstr(model, "and")) output = get_output(mif_private, get_smallest_input(mif_private));
|
||||
else output = get_output(mif_private, get_largest_input(mif_private));
|
||||
|
||||
switch (STATIC_VAR(type)) {
|
||||
case 0:
|
||||
default:
|
||||
output = get_output(mif_private, get_smallest_input(mif_private));
|
||||
break;
|
||||
case 1:
|
||||
output = get_reverse_output(mif_private,
|
||||
get_smallest_input(mif_private));
|
||||
break;
|
||||
case 2:
|
||||
output = get_output(mif_private, get_largest_input(mif_private));
|
||||
break;
|
||||
case 3:
|
||||
output = get_reverse_output(mif_private,
|
||||
get_largest_input(mif_private));
|
||||
break;
|
||||
}
|
||||
OUTPUT(out) = output;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,3 +49,11 @@ Limits: - - -
|
|||
Vector: yes yes no
|
||||
Vector_Bounds: [2 -] [2 -] -
|
||||
Null_Allowed: no no yes
|
||||
|
||||
/* This is used internally to cache the model type. */
|
||||
|
||||
STATIC_VAR_TABLE:
|
||||
|
||||
Static_Var_Name: type
|
||||
Description: "Internal copy of model type"
|
||||
Data_Type: int
|
||||
|
|
|
|||
Loading…
Reference in New Issue