
This section describes the operators and operands available in the Verilog-AMS HDL, and how to use them to form expressions.
An expression is a construct which combines operands with operators to produce a result which is a function of the values of the operands and the semantic meaning of the operator. Any legal operand, such as an integer or an indexed element from an array of reals, without a operator is also considered an expression. Wherever a value is needed in a Verilog-AMS HDL statement, an expression can be used.
Some statement constructs require an expression to be a constant expression. The operands of a constant expression consists of constant numbers and parameter names, but they can use any of the operators defined in Table 41, Table 415, and Table 416.
4.1 Operators
The symbols for the Verilog-AMS HDL operators are similar to those in the C programming language. Table 41 lists these operators.
4.1.1 Operators with real operands
The operators shown in Table 42 are legal when applied to real operands. All other operators are considered illegal when used with real operands.
The result of using logical or relational operators on real numbers is an integer value 0 (false) or 1 (true).
Table 42 lists those operators which shall not be used to operate on real numbers.
Table 4-3- Operators not allowed for real expressions === !== Case Equality ~ & | ^ ^~ ~^ Bit-wise << >> Shift {} {{}} Concatenation and replication operator
4.1.1.1 Real to integer conversion
Real numbers are converted to integers by rounding the real number to the nearest integer, rather than by truncating it. Implicit conversion takes place when a real number is assigned to an integer. The ties are rounded away from zero (0).
Examples:
// The real numbers 35.7 and 35.5 both become 36 when
// converted to an integer and 35.2 becomes 35.
// Converting -1.5 to integer yields -2, converting 1.5 to
// integer yields 2.
4.1.1.2 Arithmetic conversion
For operands, a common data type for each operand is determined before the operator is applied. If either operand is real, the other operand is converted to real. Implicit conversion takes place when a integer number is used with a real number in an operand.
Examples:
a = 3 + 5.0;
// The expression "3 + 5.0" is evaluated by "casting" the
// integer 3 to the real 3.0, and the result of the expression is 8.0.
b = 1 / 2;
// The above is integer division and the result is 0.
c = 8.0 + (1/2);
// (1/2) is treated as integer division, but the result is cast to a
// real (0.0) during the addition, and the result of the
// expression is 8.0.
4.1.2 Binary operator precedence
The precedence order of binary operators and the conditional operator (?:) is shown in Table 44.
Operators shown on the same row in Table 44 have the same precedence. Rows are arranged in order of decreasing precedence for the operators. For example, *, /, and % all have the same precedence, which is higher than that of the binary + and - operators.
All operators associate left to right with the exception of the conditional operator which associates right to left. Associativity refers to the order in which the operators having the same precedence are evaluated.
Example:
In the following example B is added to A and then C is subtracted from the result of A+B.
A + B - C
When operators differ in precedence, the operators with higher precedence associate first.
Examples:
In the following example, B is divided by C (division has higher precedence than addition) and then the result is added to A.
A + B / C
Parentheses can be used to change the operator precedence.
(A + B) / C
// not the same as A + B / C
4.1.3 Expression evaluation order
The operators follow the associativity rules while evaluating an expression as described in 4.1.2. However, if the final result of an expression can be determined early, the entire expression need not be evaluated, as long as the remaining expression does not contain analog expressions. This is called short-circuiting an expression evaluation.
Examples:
integer A, B, C, result ;
result = A & (B | C) ;
If A is known to be zero (0), the result of the expression can be determined as zero (0) without evaluating the sub-expression B | C.
4.1.4 Arithmetic operators
Table 45 shows the binary arithmetic operators.
Table 4-5- Arithmetic operators defined a + b a plus b a - b a minus b a * b a multiply by b a / b a divide by b a % b a modulo b
Integer division truncates any fractional part toward zero (0).
The unary arithmetic operators take precedence over the binary operators. Table 46 shows the unary operators.
Table 4-6- Unary operators defined +m Unary plus m (same as m) -m Unary minus m
The modulus operator, for example y % z, gives the remainder when the first operand is divided by the second, and thus is zero (0) when z divides y exactly. The result of a modulus operation takes the sign of the first operand.
For the case of the modulus operator where either argument is real, the operation performed is
a % b = a - floor(a/b)*b;
Table 47 gives examples of modulus operations.
4.1.5 Relational operators
Table 48 lists and defines the relational operators.
Table 4-8- The relational operators defined a < b a less than b a > b a greater than b a <= b a less than or equal to b a >= b a greater than or equal to b
An expression using these relational operators yields the value zero (0) if the specified relation is false or the value one (1) if it is true.
All the relational operators have the same precedence. Relational operators have lower precedence than arithmetic operators.
Examples:
The following examples illustrate the implications of this precedence rule:
a < foo - 1 // this expression is the same as
a < (foo - 1) // this expression, but . . .
foo - (1 < a) // this one is not the same as
foo - 1 < a // this expression
When foo - (1 < a) is evaluated, the relational expression is evaluated first and then either zero (0) or one (1) is subtracted from foo. When foo - 1 < a is evaluated, the value of foo operand is reduced by one (1) and then compared with a.
4.1.6 Case equality operators
The case equality operators share the same level of precedence as the logical equality operators. These operators have limited support in the analog block (see 8.3.2). Additional information on these operators can also be found in the IEEE 1364-1995 Verilog HDL.
4.1.7 Logical equality operators
The logical equality operators rank lower in precedence than the relational operators. Table 49 lists and defines the equality operators.
Table 4-9- The equality operators defined a == b a equal to b a != b a not equal to b
Both equality operators have the same precedence. These operators compare the value of the operands. As with the relational operators, the result shall be zero (0) if comparison fails, one (1) if it succeeds.
4.1.8 Logical operators
The operators logical and (&&) and logical or (||) are logical connectives. The result of the evaluation of a logical comparison can be one (1) (defined as true) or zero (0) (defined as false). The precedence of && is greater than that of || and both are lower than relational and equality operators.
A third logical operator is the unary logical negation operator (!). The negation operator converts a non-zero or true operand into zero (0) and a zero or false operand into one (1).
Examples:
The following expression performs a logical and of three sub-expressions without needing any parentheses:
a < param1 && b != c && index != lastone
However, parentheses can be used to clearly show the precedence intended, as in the following rewrite of the above example:
(a < param1) && (b != c) && (index != lastone)
4.1.9 Bit-wise operators
The bit-wise operators perform bit-wise manipulations on the operands-that is, the operator combines a bit in one operand with its corresponding bit in the other operand to calculate one bit for the result. The following logic tables (Table 410 - Table 414) show the results for each possible calculation.![]()
Table 4-14- Bit-wise unary negation operator ~ 0 1 1 0
4.1.10 Shift operators
The shift operators, << and >>, perform left and right shifts of their left operand by the number of bit positions given by the right operand. Both shift operators fill the vacated bit positions with zeroes (0). The right operand is always treated as an unsigned number.
Examples:
integer start, result;
analog begin
start = 1;
result = (start << 2);
end
In this example, the register result is assigned the binary value 0100, which is 0001 shifted to the left two positions and zero-filled.
4.1.11 Conditional operator
The conditional operator, also known as ternary operator, is right associative and shall be constructed using three operands separated by two operators, as shown in Syntax 41.
![]()
The evaluation of a conditional operator begins with the evaluation of expression1. If expression1 evaluates to false (0), then expression3 is evaluated and used as the result of the conditional expression. If expression1 evaluates to true (any value other than zero (0)), then expression2 is evaluated and used as the result.
4.1.12 Event or
The event or operator performs an or of events. See 6.7.2 for events and triggering of events.
4.1.13 Concatenations
A concatenation is used for joining scalar elements into compound elements (buses or arrays) for the built-in types integer or real, or for elements declared of type net_discipline. The concatenation shall be expressed using the brace characters ({ }), with commas separating the expressions within.
Examples:
module x;
parameter real p1[0:2] = { 1.0, 2.0, 3.0 };
...
endmodule
module y;
parameter real pole1 = 0, pole2 = 0, pole3 = 0;
x #(.p1({pole1, pole2, pole3}) x1;
...
endmodule
Module x defines a real-array parameter p1. Module y instantiates x and overrides the array value of the parameter p1 of module x via the concatenation of the scalar parameters pole1, pole2, and pole3.
Concatenations can be expressed using a replication multiplier.
Example:
{c, {2{a, b}}} // equivalent to: {c, a, b, a, b}
The replication multiplier shall be a constant expression.
4.2 Built-in mathematical functions
Verilog-AMS HDL supports the following standard mathematical functions.
4.2.1 Standard mathematical functions
The standard mathematical functions supported by Verilog-AMS HDL are shown in Table 415. The operands shall be numeric (integer or real). For min(), max(), and abs(), if either operand is real, both are converted to real, as is the result. All other arguments are converted to real.
The min(), max(), and abs() functions have discontinuous derivatives; it is necessary to define the behavior of the derivative of these functions at the point of the discontinuity. In this context, these functions are defined so:
min(x,y) is equivalent to (x < y) ? x : y
max(x,y) is equivalent to (x > y) ? x : y
abs(x) is equivalent to (x > 0) x : -x
4.2.2 Transcendental functions
The trigonometric and hyperbolic functions supported by Verilog-AMS HDL are shown in Table 416. All operands shall be numeric (integer or real) and are converted to real if necessary.
All arguments to the trigonometric and hyperbolic functions are specified in radians.
4.2.3 Error handling
All values outside of the domain for these math functions shall report an error.
4.3 Signal access functions
Access functions are used to access signals on nets, ports, and branches. There are two types of access functions, branch access functions and port access functions. The name of the access function for a signal is taken from the discipline of the net, port, or branch where the signal or port is associated and utilizes the () operator. A port access function also takes its name from the discipline of the port to which it is associated but utilizes the port access (<>) operator.
If the signal or port access function is used in an expression, the access function returns the value of the signal. If the signal access function is being used on the left side of a branch assignment or contribution statement, it assigns a value to the signal. A port access function can not be used on the left side of a branch assignment or contribution statement.
Table 417 shows how access functions can be applied to branches, nets, and ports. In this table, b1 refers to a branch, n1 and n2 represent either nets or ports, and p1 represents a port. These branches, nets, and ports are assumed to belong to the electrical discipline, where V is the name of the access function for the voltage (potential) and I is the name of the access function for the current (flow).
The argument expression list for signal access functions shall be a branch identifier, or a list of one or two nets or port expressions. If two net expressions are given as arguments to a flow access function, they shall not evaluate to the same signal. The net identifiers shall be scalar or resolve to a constant net of a composite net type (array or bus) accessed by a genvar expression.
The operands of an expression shall be unique to define a valid branch. The access function name shall match the discipline declaration for the nets, ports, or branch given in the argument expression list. In this case, V and I are used as examples of access functions for electrical potential and flow.
For port access functions, the expression list is a single port of the module. The port identifier shall be scalar or resolve to a constant net of a bus port accessed by a genvar expression. The access function name shall match the discipline declaration for the port identifier.
4.4 Analog operators
Analog operators operate on an expression and return a value. They are functions which operate on more than just the current value of their arguments. Instead, they maintain their internal state and their output is a function of both the input and the internal state.
Analog operators are also referred to as filters. They include the time derivative, time integral, and delay operators from calculus. They also include the transition and slew filters, which are used to remove discontinuity from piecewise constant and piecewise continuous waveforms. Finally, they include more traditional filters, such as those described with Laplace and Z-transform descriptions.
One special analog operator is the limexp() function, which is a version of the exp() function with built-in limits to improve convergence.
4.4.1 Restrictions on analog operators
Analog operators are subject to several important restrictions because they maintain their internal state.
· Analog operators shall not be used inside conditional (if and case) or looping (for) statements unless the conditional expression controlling the statement consists of terms which can not change their value during the course of an analysis, i.e., unless the conditional expression is a genvar expression.
· Analog operators are not allowed in the repeat and while looping statements.
· Analog operators can only be used inside an analog block; they can not be used inside an initial or always block, or inside a user-defined function.
· It is illegal to specify a null argument in the argument list of an analog operator, except as specifed elsewhere in this document.
These restrictions help prevent usage which could cause the internal state to be corrupted or become out-of-date, which results in anomalous behavior.
4.4.2 Vector or array arguments to analog operators
Certain analog operators require arrays or vectors to be passed as arguments: Laplace filters, Z-transform filters, and noise_table. An array can be passed as:
· array_identifier
· const_array_expression
A const_array_expression allows the arrays to be passed within the argument list without explicit declaration of the array object, as shown in Syntax 42.
![]()
4.4.3 Analog operators and equations
Generally, simulators formulate the mathematical description of the system in terms of first-order differential equations and solve them numerically. There is no direct way to solve a set of nonlinear differential equations so iterative approaches are used. When using iterative approaches, some criteria (tolerances) is needed to determine when the algorithm knows when it is close enough to the solution and then stops the iteration. Thus, each equation, at a minimum, shall have a tolerance defined and associated with it.
Occasionally, analog operators require new equations and new unknowns be introduced by the simulator to convert a module description into a set of first-order differential equations. In this case, the simulator attempts to determine from context which tolerance to associate with the new equation and new unknown. Alternatively, these operators can be used to specify tolerances.
Specifying natures also directly enforces reusability and allows other signal attributes to be accessed by the simulator.
4.4.4 Time derivative operator
The ddt operator computes the time derivative of its argument, as shown in Table 418.
In DC analysis, ddt() returns zero (0). The optional parameter abstol is used as an absolute tolerance if needed. Whether an absolute tolerance is needed depends on the context where ddt() is used. See 4.4.3 for more information on the application of tolerances to equations. The absolute tolerance, abstol or derived from nature, applies to the output of the ddt operator and is the largest signal level that is considered negligible.
4.4.5 Time integral operator
The idt operator computes the time-integral of its argument, as shown in Table 419.
When specified with initial conditions, idt() returns the value of the initial condition in DC and IC analyses whenever assert is given and is non-zero. Without initial conditions, idt() multiplies its argument by infinity in DC analysis. Hence, without initial conditions, it can only be used in a system with feedback which forces its argument to zero (0).
The optional parameter abstol or nature is used to derive an absolute tolerance if needed. Whether an absolute tolerance is needed depends on the context where idt() is used. (See 4.4.3 for more information.) The absolute tolerance applies to the input of the idt operator and is the largest signal level that is considered negligible.
4.4.6 Circular integrator operator
The idtmod operator, also called the circular integrator, converts an expression argument into its indefinitely integrated form similar to the idt operator, as shown in Table 420.
The initial condition is optional. If the initial condition is not specified, it defaults to zero (0). Regardless, the initial condition shall force the DC solution to the system.
If idtmod() is used in a system with feedback configuration which forces expr to zero (0), the initial condition can be omitted without any unexpected behavior during simulation. For example, an operational amplifier alone needs an initial condition, but the same amplifier with the right external feedback circuitry does not need a forced DC solution.
The output of the idtmod() function shall remain in the range
offset <= idtmod < offset+modulus
The modulus shall be an expression which evaluates to a positive value. If the modulus is not specified, then idtmod() shall behave like idt() and not limit the output of the integrator.
The default for offset shall be zero (0).
The following relationship between idt() and idtmod() shall hold at all times.
Examples:
If
y = idt(expr, ic) ;
z = idtmod(expr, ic, modulus, offset) ;
then
y = n * modulus + z ; // n is an integer
where
offset £ z < modulus + offset
In this example, the circular integrator is useful in cases where the integral can get very large, such as a VCO. In a VCO we are only interested in the output values in the range [0,2p], e.g.,
phase = idtmod(fc + gain*V(in), 0, 1, 0);
V(OUT) <+ sin(2*`M_PI*phase);
Here, the circular integrator returns a value in the range [0,1].
4.4.7 Absolute delay operator
absdelay() implements the absolute transport delay for continuous waveforms (use the transition operator to delay discrete-valued waveforms). The general form is
absdelay( input, td [, maxdelay ] )
input is delayed by the amount td. In all cases td shall be a positive number. If the optional maxdelay is specified, then td can vary; but it shall be an error if it becomes larger than maxdelay. If maxdelay is not specified, changes to td shall be ignored. If maxdelay is specified, changes to td are ignored and the initial value of maxdelay is used.
In DC and operating point analyses, absdelay() returns the value of its input. In AC and other small-signal analyses, the absdelay operator phase-shifts the input expression to the output of the delay operator based on the following formula.![]()
td is evaluated as a constant at a particular time for any small signal analysis. In time-domain analyses, absdelay() introduces a transport delay equal to the instantaneous value of td based on the following formula.![]()
The transport delay td can be either constant (typical case) or vary as a function of time (when maxdelay is defined). A time-dependent transport delay is shown in Figure 41, with a ramp input to the absdelay operator for both positive and negative changes in the transport delay td and a maxdelay of 5.
![]()
From time 0 until 2s, the output remains at input(0). With a delay of 2s, the output then starts tracking input(t - 2). At 3s, the transport delay changes from 2s to 4s, switching the output back to input(0), since input(max(t-td,0)) returns 0. The output remains at this level until 4s when it once again starts tracking the input from
t = 0. At 5s the transport delay goes to 1s and the output correspondingly jumps from its current value to the value defined by input(t - 1).
4.4.8 Transition filter
transition() smooths out piecewise constant waveforms. The transition filter is used to imitate transitions and delays on digital signals (for non-piecewise constant signals, see 4.4.9). This function provides controlled transitions between discrete signal levels by setting the rise time and fall time of signal transitions, as shown in Figure 42.
![]()
transition() stretches instantaneous changes in signals over a finite amount of time and can delay the transitions, as shown in Figure 43.
![]()
4.4.8.1 Syntax
The general form is
transition( expr [ , td [ , rise_time [ , fall_time [ , time_tol ] ] ] ] )
transition() takes the following arguments (all real-valued expressions):
· the input expression
· the delay time (shall be non-negative)
· the rise time (shall be greater than or equal to 0)
· the fall time (shall be greater than or equal to 0)
· the time_tol (shall be positive)
The input expression is expected to evaluate over time to a piecewise constant waveform. When applied, transition() forces all positive transitions of expr to occur over rise_time and all negative transitions to occur in fall_time (after an initial delay of td). Thus, td models transport delay and rise_time and fall_time model inertial delay.
transition() returns a real number which describes a piecewise linear function over time. The transition function causes the simulator to place time-points at both corners of a transition. If time_tol is not specified, the transition function causes the simulator to assure each transition is adequately resolved.
td, rise_time, fall_time, and time_tol are optional. If td is not specified, it is taken to be zero (0.0). If only a positive rise_time value is specified, the simulator uses it for both rise and fall times. If neither rise nor fall time are specified or are equal to zero (0.0), the rise and fall time default to the value defined by `default_transition.
If `default_transition is not specified the default behavior approximates the ideal behavior of a zero-duration transition. Forcing a zero-duration transition is undesirable because it could cause convergence problems. Instead, a negligible, but non-zero, transition time is used. The small non-zero transition time allows the simulator to shrink the timestep small enough so a smooth transition occurs and any convergence problems are avoided. The simulator does not force a time point at the trailing corner of a transition to avoid causing the simulator to take very small time steps, which would result in poor performance.
In DC analysis, transition() passes the value of the expr directly to its output. The transition filter is designed to smooth out piecewise constant waveforms. When applied to waveforms which vary smoothly, the simulation results are generally unsatisfactory. In addition, applying the transition function to a continuously varying waveform can cause the simulator to run slowly. Use transition() for discrete signals and slew() (see 4.4.9) for continuous signals.
If interrupted on a rising transition, transition() tries to complete the transition in the specified time.
· If the new final value level is below the value level at the point of the interruption (the current value), transition() uses the old destination as the origin.
· If the new destination is above the current level, the first origin is retained.
![]()
Figure 44 shows a rising transition is interrupted near its midpoint and the new destination level of the value below the current value. For the new origin and destination, transition() computes the slope which completes the transition from the origin (not the current value) in the specified transition time. It then uses the computed slope to transition from the current value to the new destination.
With different delays, it is possible for a new transition to be specified before a previously specified transition starts. The transition function handles this by deleting any transitions which would follow a newly scheduled transition. A transition function can have an arbitrary number of transitions pending. A transition function can be used in this way to implement transport delay for discrete-valued signals.
Because the transition function can not be linearized in general, it is not possible to accurately represent a transition function in AC analysis. The AC transfer function is approximately modeled as having unity transmission for all frequencies in all situations. Because the transition function is intended to handle discrete-valued signals, the small signals present in AC analysis rarely reach transition functions. As a result, the approximation used is generally sufficient.
4.4.8.2 Examples
Example 1 - QAM modulator
In this example, the transition function is used to control the rate of change of the modulation signal in a QAM modulator.
module qam16(out, in) ;
parameter freq=1.0, ampl=1.0, dly=0, ttime=1.0/freq ;
input [0:4] in ;
output out ;
electrical [0:4] in;
electrical out ;
real x, y, thresh;
integer row, col ;
analog begin
row = 2*(V(in[3]) > thresh) + (V(in[2]) > thresh) ;
col = 2*(V(in[1]) > thresh) + (V(in[0]) > thresh) ;
x = transition(row - 1.5, dly, ttime) ;
y = transition(col - 1.5, dly, ttime) ;
V(out) <+ ampl*x*cos(2*`M_PI*freq*$abstime)
+ ampl*y*sin(2*`M_PI*freq*$abstime) ;
$bound_step(0.1/freq) ;
end
endmodule
Example 2 - A/D converter
In this example, an analog behavioral N-bit analog to digital converter, demonstrates the ability of the transition function to handle vectors.
module adc(in, clk, out) ;
parameter bits = 8, fullscale = 1.0, dly = 0, ttime = 10n ;
input in, clk ;
output [0:bits-1] out ;
electrical in, clk;
electrical [0:bits-1] out;
real sample, thresh ;
integer result[0:bits-1];
genvar i;
analog begin
@(cross(V(clk)-2.5, +1)) begin
sample = V(in);
thresh = fullscale/2.0;
for (i = bits - 1; i >= 0; i = i - 1) begin
if (sample > thresh)
begin
result[i] = 1.0;
sample = sample - thresh ;
end else begin
result[i] = 0.0;
end
sample = 2.0*sample;
end
end
for (i = 0; i < bits; i = i + 1) begin
V(out[i]) <+ transition(result[i], dly, ttime);
end
end
endmodule
4.4.9 Slew filter
The slew analog operator bounds the rate of change (slope) of the waveform. A typical use for slew() is generating continuous signals from piecewise continuous signals. (For discrete-valued signals, see 4.4.8.) The general form is
slew( expr [ , max_pos_slew_rate [ , max_neg_slew_rate ] ] )
slew() takes the following arguments (all real numbers):
· the input expression
· the maximum positive slew rate
· the maximum negative slew rate
When applied, slew() forces all transitions of expression faster than max_pos_slew_rate to change at max_pos_slew_rate rate for positive transitions and limits negative transitions to max_neg_slew_rate rate as shown in Figure 45.
![]()
The two rate values are optional. max_pos_slew_rate shall be greater than zero(0)and max_neg_slew_rate shall be less than zero (0). If the max_neg_slew_rate is not specified, it defaults to the inverse of the max_pos_slew_rate. If no rates are specified, slew() passes the signal through unchanged. If the rate of change of expr is less than the specified maximum slew rates, slew() returns the value of expr.
In DC analysis, slew() simply passes the value of the destination to its output. In AC small-signal analyses, the slew() function has unity transfer function except when slewing, in which case it has zero transmission through the function.
4.4.10 last_crossing function
Related to the cross() function, the last_crossing() function returns a real value representing the simulation time when a signal expression last crossed zero (0). The general form is
last_crossing( expr , direction ) ;
The direction flag is interpreted in the same way as in the cross() function. The last_crossing() function is subject to the same usage restrictions as the cross() function.
The last_crossing() function does not control the timestep to get accurate results; it uses linear interpolation to estimate the time of the last crossing. However, it can be used with the cross function for improved accuracy.
Examples:
The following example measures the period of its input signal using the cross() and last_crossing() functions.
module period(in) ;
input in ;
voltage in ;
integer crossings ;
real latest, previous ;
analog begin
@(initial_step) begin
crossings = 0 ;
previous = 0 ;
end
@(cross(V(in), +1)) begin
crossings = crossings + 1 ;
previous = latest ;
end
latest = last_crossing(V(in), +1) ;
@(final_step) begin
if (crossings < 2)
$strobe("Could not measure period.") ;
else
$strobe("period = %g, crossings = %d",
latest-previous, crossings) ;
end
end
endmodule
Before the expression crosses zero (0) for the first time, the last_crossing() function returns a negative value.
4.4.11 Laplace transform filters
The Laplace transform filters implement lumped linear continuous-time filters. Each filter takes an optional parameter e, which is a real number or a nature used for deriving an absolute tolerance (if needed). Whether an absolute tolerance is needed depends on the context where the filter is used. The zeros argument may be represented as a null argument. The null argument is characterized by two adjacent commas (,,) in the argument list.
4.4.11.1 laplace_zp
laplace_zp() implements the zero-pole form of the Laplace transform filter. The general form is
laplace_zp( expr , z , r [ , e ] )
where z (zeta) is a vector of M pairs of real numbers. Each pair represents a zero, the first number in the pair is the real part of the zero and the second is the imaginary part. Similarly, r (rho) is the vector of N real pairs, one for each pole. The poles are given in the same manner as the zeros. The transfer function is![]()
whereand
are the real and imaginary parts of the
zero (0), while
and
are the real and imaginary parts of the
pole. If a root (a pole or zero) is real, the imaginary part shall be specified as zero (0). If a root is complex, its conjugate shall also be present. If a root is zero, then the term associated with it is implemented as s, rather than
(where r is the root).
4.4.11.2 laplace_zd
laplace_zd() implements the zero-denominator form of the Laplace transform filter. The general form is
laplace_zd( expr , z , d [ , e ] )
where z (zeta) is a vector of M pairs of real numbers. Each pair represents a zero, the first number in the pair is the real part of the zero and the second is the imaginary part. Similarly, d is the vector of N real numbers containing the coefficients of the denominator. The transfer function is![]()
whereand
are the real and imaginary parts of the
zero, while
is the coefficient of the
power of s in the denominator. If a zero is real, the imaginary part shall be specified as zero (0). If a zero is complex, its conjugate shall also be present. If a zero is zero (0), then the term associated with it is implemented as s, rather than
.
4.4.11.3 laplace_np
laplace_np() implements the numerator-pole form of the Laplace transform filter. The general form is
laplace_np( expr , n , r [ , e ] )
where n is a vector of M real numbers containing the coefficients of the numerator. Similarly, r (rho) is a vector of N pairs of real numbers. Each pair represents a pole, the first number in the pair is the real part of the pole and the second is the imaginary part. The transfer function is![]()
whereis the coefficient of the
power of s in the numerator, while
and
are the real and imaginary parts of the
pole. If a pole is real, the imaginary part shall be specified as zero (0). If a pole is complex, its conjugate shall also be present. If a pole is zero (0), then the term associated with it is implemented as s, rather than
.
4.4.11.4 laplace_nd
laplace_nd() implements the numerator-denominator form of the Laplace transform filter.
The general form is
laplace_nd( expr , n , d [ , e ] )
where n is an vector of M real numbers containing the coefficients of the numerator and d is a vector of N real numbers containing the coefficients of the denominator. The transfer function is![]()
whereis the coefficient of the
power of s in the numerator and
is the coefficient of the
power of s in the denominator.
4.4.11.5 Examples
V(out) <+ laplace_zp(V(in), {-1,0}, {-1,-1,-1,1});
implements![]()
and
V(out) <+ laplace_nd(V(in), {0,1}, {-1,0,1});
implements![]()
This example
V(out) <+ laplace_zp(white_noise(k), , {1,0,1,0,-1,0,-1,0});
implements a band-limited white noise source as![]()
4.4.12 Z-transform filters
The Z-transform filters implement linear discrete-time filters. Each filter supports a parameter T which specifies the sampling period of the filter. A filter with unity transfer function acts like a simple sample-and-hold which samples every T seconds and exhibits no delay. The zeros argument may be represented as a null argument. The null argument is characterized by two adjacent commas (,,) in the argument list.
All Z-transform filters share three common arguments: T, t, and t0. T specifies the period of the filter, is mandatory, and shall be positive. t specifies the transition time, is optional, and shall be nonnegative.
If the transition time is specified and is non-zero, the timestep is controlled to accurately resolve both the leading and trailing corner of the transition. If it is not specified, the transition time is taken to be one (1) unit of time (as defined by the `default_transition compiler directive) and the timestep is not controlled to resolve the trailing corner of the transition. If the transition time is specified as zero (0), then the output is abruptly discontinuous. A Z-filter with zero (0) transition time shall not be directly assigned to a branch.
Finally t0 specifies the time of the first transition, and is also optional. If not given, the first transition occurs at t=0.
4.4.12.1 zi_zp
zi_zp() implements the zero-pole form of the Z-transform filter. The general form is
zi_zp( expr , z , r , T [ , t [ , t0 ] ] )
where z (zeta) is a vector of M pairs of real numbers. Each pair represents a zero, the first number in the pair is the real part of the zero (0) and the second is the imaginary part. Similarly, r (rho) is the vector of N real pairs, one for each pole. The poles are given in the same manner as the zeros. The transfer function is![]()
whereand
are the real and imaginary parts of the
zero, while
and
are the real and imaginary parts of the
pole. If a root (a pole or zero) is real, the imaginary part shall be specified as zero. If a root is complex, its conjugate shall also be present. If a root is zero (0), then the term associated with it is implemented as z, rather than
(where r is the root).
4.4.12.2 zi_zd
zi_zd() implements the zero-denominator form of the Z-transform filter.
The form is
zi_zd( expr , z , d , T [ , t [ , t0] ] )
where z (zeta) is a vector of M pairs of real numbers. Each pair represents a zero, the first number in the pair is the real part of the zero and the second is the imaginary part. Similarly, d is the vector of N real numbers containing the coefficients of the denominator. The transfer function is![]()
whereand
are the real and imaginary parts of the
zero, while
is the coefficient of the
power of s in the denominator. If a zero is real, the imaginary part shall be specified as zero (0). If a zero is complex, its conjugate shall also be present. If a zero is zero (0), then the term associated with it is implemented as z, rather than
.
4.4.12.3 zi_np
zi_np() implements the numerator-pole form of the Z-transform filter. The general form is
zi_np( expr , n , r , T [ , t [ , t0] ] )
where n is a vector of M real numbers containing the coefficients of the numerator. Similarly, r (rho) is a vector of N pairs of real numbers. Each pair represents a pole, the first number in the pair is the real part of the pole and the second is the imaginary part. The transfer function is![]()
whereis the coefficient of the
power of s in the numerator, while
and
are the real and imaginary parts of the
pole. If a pole is real, the imaginary part shall be specified as zero (0). If a pole is complex, its conjugate shall also be present. If a pole is zero (0), then the term associated with it is implemented as z, rather than
.
4.4.12.4 zi_nd
zi_nd() implements the numerator-denominator form of the Z-transform filter. The general form is
zi_nd( expr , n , d , T [ , t [ , t0] ] )
where n is an vector of M real numbers containing the coefficients of the numerator and d is a vector of N real numbers containing the coefficients of the denominator. The transfer function is![]()
whereis the coefficient of the
power of s in the numerator and
is the coefficient of the
power of s in the denominator.
4.4.13 Limited exponential
The limexp() function is an operator whose internal state contains information about the argument on previous iterations. It returns a real value which is the exponential of its single real argument, however, it internally limits the change of its output from iteration to iteration in order to improve convergence. On any iteration where the change in the output of the limexp() function is bounded, the simulator is prevented from terminating the iteration. Thus, the simulator can only converge when the output of limexp() equals the exponential of the input. The general form is
limexp ( expr )
The apparent behavior of limexp() is not distinguishable from exp(), except using limexp() to model semiconductor junctions generally results in dramatically improved convergence. There are different ways of implementing limiting algorithms for the exponential1 2.
4.4.14 Constant versus dynamic arguments
Some of the arguments to the analog operators described in this section and the events described in Section 6 expect dynamic expressions and others expect constant expressions. The dynamic expressions can be functions of circuit quantities and can change during an analysis. The constant expressions remain static throughout an analysis.
Table 421 summarizes the arguments of the analog operators defined in this section.
If a dynamic expression is passed as an argument which expects a constant expression, the value of the dynamic expression at the start of the analysis defaults to the constant value of the argument. Any further change in value of that expression is ignored during the iterative analysis.
4.5 Analysis dependent functions
This section describes the analysis() function, which is used to determine what type of analysis is being performed, and the small-signal source functions. The small-signal source functions only affect the behavior of a module during small-signal analyses. The small-signal analyses provided by SPICE include the AC and noise analyses, but others are possible. When not active, the small-signal source functions return zero (0).
4.5.1 Analysis
The analysis() function takes one or more string arguments and returns one (1) if any argument matches the current analysis type. Otherwise it returns zero (0). The general form is
analysis( analysis_list )
There is no fixed set of analysis types. Each simulator can support its own set. However, simulators shall use the types listed in Table 422 to represent analyses which are similar to those provided by SPICE.
Any unsupported type names are assumed to not be a match.
Table 423 describes the implementation of the analysis function. Each column shows the return value of the function. A status of one (1) represents True and zero (0) represents False.
Using the analysis() function, it is possible to have a module behave differently depending on which analysis is being run.
Examples:
To implement nodesets or initial conditions using the analysis function and switch branches, use the following.
if (analysis("ic"))
V(cap) <+ initial_value;
else
I(cap) <+ ddt(C*V(cap));
4.5.2 AC stimulus
A small-signal analysis computes the steady-state response of a system which has been linearized about its operating point and is driven by a small sinusoid. The sinusoidal stimulus is provided using the ac_stim() function. The general form is
ac_stim( [analysis_name [ , mag [ , phase ] ] ] )
The AC stimulus function returns zero (0) during large-signal analyses (such as DC and transient) as well as on all small-signal analyses using names which do not match analysis_name. The name of a small-signal analysis is implementation dependent, although the expected name (of the equivalent of a SPICE AC analysis) is "ac", which is the default value of analysis_name. When the name of the small-signal analysis matches analysis_name, the source becomes active and models a source with magnitude mag and phase phase. The default magnitude is one (1) and the default phase is zero (0). phase is given in radians.
4.5.3 Noise
Several functions are provided to support noise modeling during small-signal analyses. To model large-signal noise during transient analyses, use the $random() system task. The noise functions are often referred to as noise sources. There are three noise functions, one models white noise processes, another models 1/f or flicker noise processes, and the last interpolates a vector to model a process where the spectral density of the noise varies as a piecewise linear function of frequency. The noise functions are only active in small-signal noise analyses and return zero (0) otherwise.
4.5.3.1 white_noise
White noise processes are those whose current value is completely uncorrelated with any previous or future values. This implies their spectral density does not depend on frequency. They are modeled using
white_noise( pwr [ , name ] )
which generates white noise with a power of pwr.
Examples:
The thermal noise of a resistor could be modelled using
I(a,b) <+ V(a,b)/R +
white_noise(4 * `P_K * $temperature/R, "thermal");
The optional name argument acts as a label for the noise source used when the simulator outputs the individual contribution of each noise source to the total output noise. The contributions of noise sources with the same name from the same instance of a module are combined in the noise contribution summary.
4.5.3.2 flicker_noise
The flicker_noise() function models flicker noise. The general form is
flicker_noise( pwr , exp [ , name ] )
which generates pink noise with a power of pwr at 1Hz which varies in proportion to
1/f exp.
The optional name argument acts as a label for the noise source used when the simulator outputs the individual contribution of each noise source to the total output noise. The contributions of noise sources with the same name from the same instance of a module are combined in the noise contribution summary.
4.5.3.3 noise_table
The noise_table() function interpolates a vector to model a process where the spectral density of the noise varies as a piecewise linear function of frequency. The general form is
noise_table( vector [ , name ] )
where vector contains pairs of real numbers: the first number in each pair is the frequency in Hertz and the second is the power. Noise pairs are specified in the order of ascending frequencies. noise_table() performs piecewise linear interpolation to compute the power spectral density generated by the function at each frequency.
The optional name argument acts as a label for the noise source used when the simulator outputs the individual contribution of each noise source to the total output noise. The contributions of noise sources with the same name from the same instance of a module are combined in the noise contribution summary.
4.5.3.4 Noise model for diode
The noise of a junction diode could be modelled as shown in the following example.
I(a,c) <+ is*(exp(V(a,c) / (n * $vt)) - 1)
+ white_noise(2*`P_Q*I(<a>))
+ flicker_noise(kf*pow(abs(I(<a>)), af), ef);
4.5.3.5 Correlated noise
Each noise function generates noise which is uncorrelated with the noise generated by other functions. Perfectly correlated noise is generated by using the output of one noise function for more than one noise source. Partially correlated noise is generated by combining the output of shared and unshared noise functions.
Examples:
Example 1 - Two noise voltages are perfectly correlated.
n = white_noise(pwr);
V(a,b) <+ c1*n;
V(c,d) <+ c2*n;
Example 2 - Partially correlated noise sources can also be modelled.
n1 = white_noise(1-corr);
n2 = white_noise(1-corr);
n12 = white_noise(corr);
V(a,b) <+ Kv*(n1 + n12);
I(b,c) <+ Ki*(n2 + n12);
4.6 User-defined functions
A user-defined function can be used to return a value (for an expression). All functions are defined within modules. Each function can be an analog function or a digital function (as defined in IEEE 1364-1995 Verilog HDL).
4.6.1 Defining an analog function
The syntax for defining an analog function is shown in Syntax 43.
![]()
An analog function declaration shall begin with the keywords analog function, optionally followed by the type of the return value from the function, then the name of the function and a semicolon, and ending with the keyword endfunction.
type specifies the return value of the function; its use is optional. type can be a real or an integer; if unspecified, the default is real.
An analog function:
· can use any statements available for conditional execution (see 6.1);
· shall not use access functions;
· shall not use contribution statements or event control statements;
· shall have at least one input declared; the block item declaration shall declare the type of the inputs as well as local variables used in the function.
· shall not use named blocks; and
· shall only reference locally-defined variables or variables passed as arguments.
Examples:
The following example defines an analog function called maxValue, which returns the potential of whichever signal is larger.
analog function real maxValue;
input n1, n2 ;
real n1, n2 ;
begin
// code to compare potential of two signal
maxValue = (n1 > n2) ? n1 : n2 ;
end
endfunction
4.6.2 Returning a value from an analog function
The analog function definition implicitly declares a variable, internal to the analog function, with the same name as the analog function. This variable has the same type as the type specified in the analog function declaration. The analog function definition initializes the return value from the analog function by assigning the analog function result to the internal variable with the same name as the analog function. This variable can be read and assigned within the flow; its last assigned value is passed back on the return call.
Example:
The following line (from the example in 4.6.1) illustrates this concept:
maxValue = (n1 > n2) ? n1 : n2 ;
If the internal variable is not assigned, the function shall return zero (0).
4.6.3 Calling an analog function
An analog function call is an operand within an expression. Syntax 44 shows the analog function call.
![]()
The order of evaluation of the arguments to an analog function call is undefined.
An analog function:
· shall not call itself directly or indirectly, i.e., recursive functions are not permitted;
· shall only be called within an analog block; and
· can be called outside of their immediate scope.
Example:
The following example uses the maxValue function defined in 4.6.1.
V(out) <+ maxValue(val1, val2) ;
1 Laurence W. Nagel, "SPICE2: A computer program to simulate semiconductor circuits," Memorandum No. ERL-M520, University of California, Berkeley, California, May 1975.
2 W. J. McCalla, Fundamentals of Computer-Aided Circuit Simulation. Kluwer Academic Publishers, 1988.
|
Quadralay Corporation http://www.webworks.com Voice: (512) 719-3399 Fax: (512) 719-3606 sales@webworks.com |