Product Documentation
Cadence Verilog-AMS Language Reference
Product Version 22.09, April 2022

9


Simulator Functions

This chapter describes the Cadence® Verilog®-AMS language simulator functions. The simulator functions let you access information about a simulation and manage the simulation’s current state. You can also use the simulator functions to display and record simulation results.

For information about using simulator functions, see

For information on analog operators and filters, see

For descriptions of functions used to control input and output, see

For descriptions of functions used to control the simulator, see

For a description of the $pwr function, which is used to specify power consumption in a module, see

For information on using user-defined functions in the Verilog-AMS language, see

Announcing Discontinuity

Use the $discontinuity function to tell the simulator about a discontinuity in signal behavior.

discontinuity_function ::=
        $discontinuity[ (constant_expression) ]

constant_expression, which must be zero or a positive integer, is the degree of the discontinuity. For example, $discontinuity, which is equivalent to $discontinuity(0), indicates a discontinuity in the equation, and $discontinuity(1) indicates a discontinuity in the slope of the equation.

You do not need to announce discontinuities created by switch branches or built-in functions such as transition and slew.

Be aware that using the $discontinuity function does not guarantee that the simulator will be able to handle a discontinuity successfully. If possible, you should avoid discontinuities in the circuits you model.

The following example shows how you might use the $discontinuity function while describing the behavior of a source that generates a triangular wave. As the Triangular Wave figure shows, the triangular wave is continuous, but as the Triangular Wave First Derivative figure shows, the first derivative of the wave is discontinuous.

Triangular Wave

Triangular Wave First Derivative

The module trisource describes this triangular wave source.

module trisource (vout) ;
output vout ;
voltage vout ;
parameter real wavelength = 10.0, amplitude = 1.0 ;
integer slope ;
real wstart ;
analog begin
    @(timer(0, wavelength)) begin
        slope = +1 ;
        wstart = $abstime ;
        $discontinuity (1);        // Change from neg to pos slope
    end
    @(timer(wavelength/2, wavelength)) begin
        slope = -1 ;
        wstart = $abstime ;
        $discontinuity (1);        // Change from pos to neg slope
    end
    V(vout) <+ amplitude * slope * (4 * ($abstime - wstart) / wavelength-1) ;
end
endmodule

The two $discontinuity functions in trisource tell the simulator about the discontinuities in the derivative. In response, the simulator uses analysis techniques that take the discontinuities into account.

The module relay, as another example, uses the $discontinuity function while modeling a relay.

module relay (c1, c2, pin, nin) ;
inout c1, c2 ;
input pin, nin ;
electrical c1, c2, pin, nin ;
parameter real r = 1 ;
analog begin
    @(cross(V(pin, nin) - 1, 0, 0.01n, pin.potential.abstol)) $discontinuity(0);
    if (V(pin, nin) >= 1)
        I(c1, c2) <+ V(c1, c2) / r ;
    else
        I(c1, c2) <+ 0 ;
end
endmodule

The $discontinuity function in relay tells the simulator that there is a discontinuity in the current when the voltage crosses the value 1. For example, passing a triangular wave like that shown in the Relay Voltage figure through module relay produces the discontinuous current shown in the Relay Current figure.

Relay Voltage

Relay Current

Bounding the Time Step

Use the $bound_step function to specify the maximum time allowed between adjacent time points during simulation.

bound_step_function ::=
        $bound_step ( max_step )
max_step ::=
        constant_expression

By specifying appropriate time steps, you can force the simulator to track signals as closely as your model requires. For example, module sinwave forces the simulator to simulate at least 50 time points during each cycle.

module sinwave (outsig) ;
output outsig ;
voltage outsig ;
parameter real freq = 1.0, ampl = 1.0 ;
analog begin
    V(outsig) <+ ampl * sin(2.0 * ‘M_PI * freq * $abstime) ;
    $bound_step(0.02 / freq) ;            // Max time step = 1/50 period
end
endmodule

Announcing and Handling Nonlinearities

Use the $limit function to announce nonlinearities that are other than exponential. This information is used to improve convergence.

limit_call_function ::=
        $limit ( access_function_reference )
|   $limit ( access_function_reference, string, arg_list)
|   $limit ( access_function_reference, analog_function_ID, arg_list)

access_function_reference is the reference that is being limited.

string is a built-in simulator function that you recommend be used to compute the return value. In this release, the syntax of string is not checked.

analog_function_ID is a user-defined analog function that you recommend be used to compute the return value. In this release, the syntax of analog_function_ID is not checked.

arg_list is a list of arguments for the built-in or user-defined function. In this release, the syntax of arg_list is not checked.

Although the $limit function is allowed, Cadence tools, in this release, do nothing with the information. Consequently, coding
vdio = $limit(V(a,c), spicepnjlim, $vt, vcrit);

is equivalent to coding

vdio = V(a,c);

Finding When a Signal Is Zero

Use the last_crossing function to find out what the simulation time was when a signal expression last crossed zero.

last_crossing_function ::=
        last_crossing ( signal_expression , direction )

Set direction to indicate which crossings the simulator should detect.

If you want to Then

Detect all crossings

Set direction equal to 0

Detect only crossings where the value is increasing

Set direction equal to +1

Detect only crossings where the value is decreasing

Set direction equal to -1

Before the first detectable crossing, the last_crossing function returns a negative value.

The last_crossing function is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

The last_crossing function does not control the time step to get accurate results and uses interpolation to estimate the time of the last crossing. To improve the accuracy, you might want to use the last_crossing function together with the cross function.

For example, module period calculates the period of the input signal, using the cross function to resolve the times accurately.

module period (in) ;
input in ;
voltage in ;
integer crosscount ;
real latest, earlier ;
analog begin
    @(initial_step) begin
        crosscount = 0 ;
        earlier = 0 ;
    end
 @(cross(V(in), +1)) begin
crosscount = crosscount + 1 ;
earlier = latest ;
end
latest = last_crossing(V(in), +1) ;
@(final_step) begin
if (crosscount < 2)
$strobe("Could not measure the period.") ;
else
$strobe("Period = %g, Crosscount = %d", latest-earlier, crosscount) ;
end
end
endmodule

Querying the Simulation Environment

Use the simulation environment functions described in the following sections to obtain information about the current simulation environment.

Obtaining the Current Simulation Time

Verilog-AMS provide two environment parameter functions that you can use to obtain the current simulation time: $abstime and $realtime.

$abstime Function

Use the $abstime function to obtain the current simulation time in seconds.

abstime_function ::=
        $abstime

$realtime Function

Use the $realtime function to obtain the current simulation time in seconds.

realtime_function ::=
        $realtime[(time_scale)]

time_scale is a value used to scale the returned simulation time. The valid values are the integers 1, 10, and 100, followed by one of the scale factors in the following table.

Scale Factor Meaning

s

Seconds

ms

Milliseconds

us

Microseconds

ns

Nanoseconds

ps

Picoseconds

fs

Femtoseconds

If you do not specify time_scale, the return value is scaled to the ‘time_unit of the module that invokes the function.

For example, to print out the current simulation time in seconds, you might code

$strobe("Simulation time = %e", $realtime(1s)) ; 

Obtaining the Current Ambient Temperature

Use the $temperature function to obtain the ambient temperature of a circuit in degrees Kelvin.

temperature_function ::=
        $temperature

The $temperature function is supported in both analog and digital contexts. In digital context, the $temperature function can be used only in initial and always blocks, continuous assignments, and system tasks and functions. It is not supported in port connections.

In a digital mixed-signal design (DMS), the $temperature function returns the value 300.15 degree Kelvin units by default.

Obtaining the Thermal Voltage

Use the $vt function to obtain the thermal voltage, (kT/q), of a circuit.

vt_function ::=
        $vt[(temp)]

temp is the temperature, in degrees Kelvin, at which the thermal voltage is to be calculated. If you do not specify temp, the thermal voltage is calculated at the temperature returned by the $temperature function.

Querying the scale, gmin, and iteration Simulation Parameters

Use the $simparam function to query the value of the scale, gmin, or iteration simulation parameters. The returned value is always a real value.

simparam_function ::=
        $simparam ("param" [, expression])

param is one of the following simulation parameters.

Simulation Parameter Meaning

scale

Scale factor for device instance geometry parameters.

gmin

Minimum conductance placed in parallel with nonlinear branches.

iteration

Iteration number of the analog solver.

expression is an expression whose value is returned if param is not recognized.

For example, to return the value of the simulation parameter named gmin, you might code

$strobe("gmin = %e", $simparam("gmin")) ; 

To specify that a value of 2.0 is to be returned when the specified simulation parameter is not found, you might code

$strobe("gmin = %e", $simparam("gmin", 2.0)) ;

Probing of values Within a Sibling Instance During Simulation

Dynamic simulation probe function

Verilog-AMS HDL supports Dynamic Simulation Probe function $simprobe() that allows probing of values within a sibling instance during simulation.

Syntax

$simprobe( <inst_name> (string), <param_name> (string), [ optional real valued expression ] )

If a parameter is not found and the optional real valued expression is set, then that would be the output.

$simprobe() queries the simulator for an output variable named param_name in a sibling instance called inst_name. The arguments inst_name and param_name are string values (either a string literal, string parameter, or a string variable).

To resolve the value, the simulator looks for an instance called inst_name in the parent of the current instance, that is, a sibling of the instance containing the $simprobe() expression. Once the instance is resolved, it then queries that instance for an output variable called param_name. If either the inst_name or param_name cannot be resolved, and the optional expression is not supplied, an error is displayed. If the optional expression is supplied, its value is displayed.

The intended use of this function is to allow dynamic monitoring of instance quantities.

Example

module monitor;
parameter string inst = "default";
parameter string quant = "default";
parameter real threshold = 0.0;
real probe;
analog begin
    probe = $simprobe(inst,quant);
    if (probe > threshold) begin
    $strobe("ERROR: Time %e: %s#%s (%g) > threshold (%e)",
    $abstime, inst,quant, probe, threshold);
    $finish;
end
end
endmodule

The module monitor probes the quant in instance inst. If its value becomes larger than threshold, an error is raised and the simulation is stopped.

module top(d,g,s);
electrical d.g.s;
inout d,g,s;
electrical gnd; ground gnd;
    SPICE_pmos #(.w(4u),.l(0.1u).ad(4p),.as(4p),.pd(10u),.ps(10u))
    mp(d,g,s,s);
    SPICE_nmos #(.w(2u),.l(0.1u),.ad(2p),.as(2p),.pd(6u),.ps(6u))
    mn(d,g,gnd,gnd);
    monitor #(.inst("mn"),.quant("id"),.threshold(4.0e-3))
    amonitor();
endmodule

Here the monitor instance amonitor keeps track of the dynamic quantity id in the mosfet instance mn. If the value of id goes above the specified threshold of 4.0e-3 amps, the instance amonitor generates the error message and stops the simulation.

Probing using $simprobe$str

In digital context, $simprobe$str allows probing of values within a sibling instance during simulation.

Syntax

$simprobe$str( <inst_name> (string), <param_name> (string), [ optional string expression] )

Example

module monitor;
    string val1, val2, val3, val4;
    string path = "I1.XI40.MM1";
    string default_val = "default";
    real count;
    initial begin
        val1 = $simprobe$str(path,"region");
        $display("\n === (digital) value of region is: %s\n", val1);
        
        val2 = $simprobe$str(path,"error",default_val);
        $display("\n === (digital) value of region (default) is %s\n", val2);
    end
    analog begin
        @ (initial_step) begin
            count=0;
        end
        if( count < 5 ) begin
            val3 = $simprobe$str(path,"region");
            $display("\n === (analog) value of region is: %s\n", val3);
                        
            val4 = $simprobe$str(path,"error", default_val);
            $display("\n === (analog) value of region (default) is %s\n", val4);
        end
        count = count+1;
    end
endmodule
module top (output clk_out);
wire comp, start_, ck1, ld;
wire clk_in, start;
wire [5:0] b;
dll_dig I2 ( .b( b), .clk_in( clk_in), .start( start), .ck1( ck1), 
    .comp( comp), .ld( ld), .start_( start_));
dll_spice I1 ( .mybit( b), .start( start), .clk_in( clk_in), 
    .clk_out(clk_out), .ck1( ck1), .comp( comp), .ld( ld), 
    .start_( start_));
monitor m1();
endmodule

Obtaining and Setting Signal Values

Use the access functions to obtain or set the signal values.

access_function_reference ::=
        bvalue
    |   pvalue
bvalue ::=
        access_identifier ( analog_signal_list )
pvalue ::=
     access_identifier (<port_scalar_expression>)
access_identifier ::=
    nature_access_identifier
    |potential
    |flow
analog_signal_list ::=
        branch_identifier
| array_branch_identifier [ genvar_expression ]
| net_or_port_scalar_expression
|   net_or_port_scalar_expression , net_or_port_scalar_expression
net_or_port_scalar_expression ::=
        net_or_port_identifier
|   vector_net_or_port_identifier [ genvar_expression ]
port_scalar_expression ::=
        port_identifier
|   array_port_identifier [ constant_expression ]     |   vector_port_identifier [ constant_expression ]

Access functions in Verilog-AMS take their names from the discipline associated with a node, port, or branch. Specifically, the access function names are defined by the access attributes specified for the discipline’s natures.

For example, the electrical discipline, as defined in the standard definitions, uses the nature Voltage for potential. The nature Voltage is defined with the access attribute equal to V. Consequently, the access function for electrical potential is named V. For more information, see the files installed in your_install_dir/tools/spectre/etc/ahdl.

To set a voltage, use the V access function on the left side of a contribution statement.

V(out) <+ I(in) * Rparam ;

To obtain a voltage, you might use the V access function as illustrated in the following fragment.

I(c1, c2) <+ V(c1, c2) / r ;

You can also use the potential or flow access function to access the potential or flow of a named or unnamed branch. If an unnamed branch comprises of two nets, ensure that the disciplines of both nets is the same before using the potential and flow functions, as shown below.

electrical in, out;
potential( in, out ) <+ flow( in, out ) * 1k;

The simulator provides specialized support for obtaining (from analog contexts only) the voltages of nets or ports specified by out-of-module references. For example, you can use a block like the following:

analog begin
tmp_a_b = V(top.level1.level2.node_a, top.level1.level2.node_b);
tmp_a = V(top.level1.level2.node_a);
tmp_c_b = V(top.level1.level2.node_c[1], top.level1.level2.node_b[1]);
$display("tmp_a_b = %g, tmp_a = %g, tmp_c_b =%g\n", tmp_a_b, tmp_a, tmp_c_b);
end

If you want to set the voltage on a net or port that is an out-of-module reference, you must be sure to define the discipline of that net or port explicitly as electrical. For example:

// Contents of oomr.v 
`include "disciplines.vams"
module top;    electrical a; // node a referenced in module sub
electrical gnd;
   sub (* integer library_binding = "work_lib"; *) Isub ( );
   resistor #(.r(1.000)) (* integer library_binding = "analogLib"; *) R1 (a, gnd);
   analog begin
V(gnd) <+ 0.0;
V(Isub.b) <+ 18.0; // out-of-module reference to node b,
// explicitly declared as electrical in module sub
end
endmodule
// Contents of sub.v
`include "disciplines.vams"
module sub;    electrical b; // node b referenced in module top
   electrical gnd;
   resistor #(.r(1.000)) (* integer library_binding = "analogLib"; *) R1 (b ,gnd );
   analog begin
V(top.a) <+ 17.0; // out-of-module reference to top.a,
// explicitly declared as electrical in module top
V(gnd)<+ 0.0;
end
endmodule

The simulator provides limited support for obtaining (from analog contexts only) the currents of nets or ports specified by out-of-module references. For more information, see “Obtaining Currents Using Out-of-Module References”.

You can apply access functions only to scalars or to individual elements of a vector. You select the scalar element of a vector using an index. For example, V(in[1]) accesses the voltage in[1].

To see how you can use access functions, see the “Access Function Formats” table, below. In the table, b1 refers to a branch, n1 and n2 refer to either nodes or ports, and p1 refers to a port. The branches, nodes, and ports in this table 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). Access functions for other disciplines have different names, but you use them in the same ways. For example, MMF is the access function for potential in the magnetic discipline.

Access Function Formats

Format Effect

V(b1)

Accesses the potential across branch b1

potential(b1)

Alternative method to access the voltage across branch b1

V(n1)

Accesses the potential of n1 relative to ground

V(n1,n2)

Accesses the potential difference on the unnamed branch between n1 and n2

I(b1)

Accesses the current on branch b1

flow(b1)

Alternative method to access the current on branch b1

I(n1)

Accesses the current flowing from n1 to ground

I(n1, n2)

Accesses the current flowing on the unnamed branch between n1 and n2; node n1 and node n2 cannot be the same node

I(<p1>)

Accesses the current flow into the module through port p1.

Notice the use of the port access operator (<>) in the last format. The port identifier in a port access function must be a scalar or resolve to a constant node of a bus port accessed by a constant expression. You cannot use the port access operator to access potential, nor can you use the port access operator on the left side of a contribution operator. You can use the port access operator only in modules that do not instantiate sub-hierarchies or primitives.

You can use a port access to monitor the flow. In the following example, the simulator issues a warning if the total diode current becomes too large.

module diode (a, c) ;
electrical a, c ;
branch (a, c) diode, cap ;
parameter real is=1e-14, tf=0, cjo=0, imax=1, phi=0.7 ;
analog begin
    I(diode) <+ is*(limexp(V(diode)/$vt) -1) ;
    I(cap) <+ ddt(tf*I(diode) - 2 * cjo * sqrt(phi * (phi * V(cap)))) ;
    if (I(<a>) > imax) // Checks current through port
        $strobe( "Warning: diode is melting!" ) ;
    end 
endmodule

Obtaining Currents Using Out-of-Module References

Use the Cadence-provided system task $cds_iprobe to return the current of an out-of-module port.

OOM_current_reference ::=
        $cds_iprobe("hierarchical_name")

hierarchical_name is the hierarchical name of the out-of-module scalar port or individual bit of a vector port whose current you want to access.

The $cds_iprobe task is subject to the following limitations:

For example, you set up a Tcl probe with the following command.

xcelium> probe -create -flow -shm -port top.I1

You create and simulate the following modules:

module top;
electrical a, gnd;
ground gnd;
real x;
vsource #(.type("sine"), .ampl(11), .freq(1k)) V1(a,gnd);
leaf l1(a,gnd);
analog begin
// The top.I1.a below is an out-of-module reference.
$display("I<top.l1.a>=%g\n", $cds_iprobe("top.l1.a"));
end
endmodule
module leaf(a,b);
electrical a, b;
resistor #(.r(1.0)) r1(a,b);
Endmodule

The $display statement in the analog block displays the current of port a in the instance of the leaf module.

Accessing Attributes

Use the hierarchical referencing operator to access the attributes for a node or branch.

attribute_reference ::=
        node_identifier.pot_or_flow.attribute_identifier
pot_or_flow ::=
        potential
|   flow

node_identifier is the node or branch whose attribute you want to access.

attribute_identifier is the attribute you want to access.

For example, the following fragment illustrates how to access the abstol values for a node and a branch.

electrical a, b, n1, n2;
branch (n1, n2) cap ;
parameter real c= 1p;
analog begin 
    I(a,b) <+ c*ddt(V(a,b), a.potential.abstol) ;  // Access abstol for node
    I(cap) <+ c*ddt(V(cap), n1.potential.abstol) ; // Access abstol for branch
end

Examining Drivers

A driver of a signal is one of the following:

Each driver can have both a present value and a pending value. The present value is the present contribution of the driver to the signal. The pending value is the next scheduled contribution, if any, of the driver to the signal.

The drivers associated with a signal are numbered from zero to one less than the number of drivers. For example, if there are five associated drivers, then they have the numbers 0, 1, 2, 3, and 4.

The next sections describe the Verilog-AMS driver access functions you can use to create connect modules that are controlled by the digital drivers in ordinary modules. Note that

Counting the Number of Drivers

Use the $driver_count function to determine how many drivers are associated with a specified digital signal.

driver_count_function ::=
        $driver_count ( signal )

signal is the name of the digital signal.

The $driver_count function returns an integer, which is the number of drivers associated with signal.

Determining the Value Contribution of a Driver

Use the driver_state function to determine the present value contribution of a specified driver to a specified signal.

driver_state_function ::=
        $driver_state ( signal , driver_index )

signal is the name of the digital signal.

driver_index is an integer number between 0 and N-1 where N is the total number of drivers contributing to the signal value.

The driver_state function returns one of the following state values: 0, 1, x, or z.

Determining the Strength of a Driver

Use the driver_strength function to determine the strength contribution of a specified driver to a specified signal.

driver_strength_function ::=
        $driver_strength ( signal , driver_index )

signal is the name of the digital signal.

driver_index is an integer number between 0 and N-1 where N is the total number of drivers contributing to the signal value.

The driver_strength function returns two strengths: bits 5 through 3 for strength0 and bits 2 through 0 for strength1.

If the value returned is 0 or 1, strength0 returns the high end of the strength range and strength1 returns the low end of the strength range. Otherwise, the strengths of both strength0 and strength1 are defined as shown below.

strength0 strength1

Bits

7

Su0

6

St0

5

Pu0

4

La0

3

We0

2

Me0

1

Sm0

0

HiZ0

0

HiZ1

1

Sm1

2

Me1

3

We1

4

La1

5

Pu1

6

St1

7

Su1

Bits

B5

1

1

1

1

0

0

0

0

0

0

0

0

1

1

1

1

B2

B4

1

1

0

0

1

1

0

0

0

0

1

1

0

0

1

1

B1

B3

1

0

1

0

1

0

1

0

0

1

0

1

0

1

0

1

B0

For more information, see the “Logic Strength Modeling” section, of the “Gate and Switch Level Modeling” chapter, in the Verilog-XL Reference.

Detecting Updates to Drivers

Use the driver_update event keyword to determine when a driver of a signal is updated by the addition of a new pending value.

driver_update_event_keyword ::=
        driver_update ( signal )

signal is the name of the digital signal.

The driver_update event occurs any time a new pending value is added to the driver, even when there is no change in the resolved value of the signal.

Use the driver_update event keyword in conjunction with the event detection operator to detect updates. For example, the statement in the following code executes any time a driver of the clock signal is updated.

always @ (driver_update clock)
    statement ;

Analysis-Dependent Functions

The analysis-dependent functions change their behavior according to the type of analysis being performed.

Determining the Current Analysis Type

Use the analysis function to determine whether the current analysis type matches a specified type. By using this function, you can design modules that change their behavior during different kinds of analyses.

analysis ( analysis_list )
analysis_list ::=
        analysis_name { , analysis_name }
analysis_name ::=
        "analysis_type"

analysis_type is one of the following analysis types.

Analysis Types and Descriptions

Analysis Type Analysis Description

dc

OP or DC analysis

static

Any equilibrium point calculation, including a DC analysis as well as those that precede another analysis, such as the DC analysis that precedes an AC or noise analysis, or the initial-condition analysis that precedes a transient analysis

tran

Transient analysis

The following table describes the values returned by the analysis function for some of the commonly used analyses. A return value of 1 represents TRUE and a value of 0 represents FALSE.

Simulator Analysis Type
Argument DC TRAN OP TRAN AC OP AC NOISE OP AC

static

1

1

0

1

0

1

0

ic

0

1

0

0

0

0

0

dc

1

0

0

0

0

0

0

tran

0

1

1

0

0

0

0

ac

0

0

0

1

1

0

0

noise

0

0

0

0

0

1

1

You can use the analysis function to make module behavior dependent on the current analysis type.

if (analysis("dc", "ic"))
    out = ! V(in) > 0.0 ;
else
    @(cross (V(in),0)) out = ! out
V(out) <+ transition (out, 5n, 1n, 1n) ;

Implementing Small-Signal AC Sources

Use the ac_stim function to implement a sinusoidal stimulus for small-signal analysis.

ac_stim ( [ "analysis_type" [ , mag [ , phase]]] )

analysis_type, if you specify it, must be one of the analysis types listed in the Analysis Types and Descriptions table. The default for analysis_type is ac. The mag argument is the magnitude, with a default of 1. phase is the phase in radians, with a default of 0.

The ac_stim function models a source with magnitude mag and phase phase only during the analysis_type analysis. During all other small-signal analyses, and during large-signal analyses, the ac_stim function returns 0.

Implementing Small-Signal Noise Sources

Verilog-AMS provides three functions to support noise modeling during small-signal analyses:

White_noise Function

Use the white_noise function to generate white noise, noise whose current value is completely uncorrelated with any previous or future values.

white_noise( PSD [ , "name"])

PSD is the power spectral density of the source where PSD is specified in units of A2/Hz or V2/Hz.

name is a label for the noise source. The simulator uses name to identify the contributions of noise sources to the total output noise. The simulator combines into a single source all noise sources with the same name from the same module instance.

The white_noise function is active only during small-signal noise analyses and returns 0 otherwise.

For example, you might include the following fragment in a module describing the behavior of a diode.

I(diode) <+ white_noise(2 * ‘P_Q * Id, "shot" ) ;

For a resistor, you might use a fragment like the following.

V(res) <+ white_noise(4 * ‘P_K * $temperature * rs, "thermal");

flicker_noise Function

Use the flicker_noise function to generate pink noise that varies in proportion to:

The syntax for the flicker_noise function is

flicker_noise( power, exp [ , "name"])

power is the power of the source at 1 Hz.

name is a label for the noise source. The simulator uses name to identify the contributions of noise sources to the total output noise. The simulator combines into a single source all noise sources with the same name from the same module instance.

The flicker_noise function is active only during small-signal noise analyses and returns 0 otherwise.

For example, you might include the following fragment in a module describing the behavior of a diode:

I(diode) <+ flicker_noise( kf * pow(abs(I(diode)),af),ef) ;

noise_table Function

Use the noise_table function to generate noise where the spectral density of the noise varies as a piecewise linear function of frequency.

noise_table(vector | string [ , "name" ])

The first argument to the noise_table function is a vector or a string.

vector is an array containing pairs of real numbers. The first number in each pair represents the frequency in hertz and the second number is the power at that frequency.

string is an input file containing frequency and power values specified in pairs. Each pair is specified in a new line and is separated by space(s) or tab(s). You can comment a line by inserting a comment (#) at the beginning of the line. Comments end with a new line. The input file can only be a text file and the values must be real numbers or integers. In addition, each frequency value must be unique.

It is recommended that you specify each noise pair in the order of ascending frequency. However, if required, the simulator internally sorts the pairs in the order of ascending frequency.

The noise_table function uses the linear interpolation method to calculate the spectral density for each frequency. The power associated with the lowest frequency specified in the table is taken as the associated power for all frequencies below the smallest frequency. Similarly, the power associated with the highest frequency specified in the table is taken as the associated power for all frequencies above the highest frequency.

The following is an example of the input file:

# noise_table_input.tbl
# Example of input file format for noise_table
#
# freq        pwr
1.0e0       1.348720e-23
1.0e1       5.482480e-23
1.0e2       7.135790e-23
1.0e3       1.811153e-22
1.0e4       3.726892e-22
1.0e5       7.412361e-22
1.0e6       2.172611e-21
# End

name is a label for the noise source. The simulator uses name to identify the contributions of noise sources to the total output noise. The simulator combines into a single source all noise sources with the same name from the same module instance.

The noise_table function is active only during small-signal noise analyses and returns 0 otherwise.

For example, you might include the following fragment in an analog block:

V(p,n) <+ noise_table({1,2,100,4,1000,5,1000000,6}, "noitab");

In this example, the power at every frequency lower than 1 is assumed to be 2; the power at every frequency above 1000000 is assumed to be 6.

Generating Random Numbers

Use the $random function to generate a signed integer, 32-bit, pseudorandom number.

$random [ ( seed ) ] ;

seed is a reg, integer, or time variable used to initialize the function. The seed provides a starting point for the number sequence and allows you to restart at the same point. If, as Cadence recommends, you use seed, you must assign a value to the variable before calling the $random function.

The $random function generates a new number every time step.

Individual $random statements with different seeds generate different sequences, and individual $random statements with the same seed generate identical sequences.

The following code fragment uses the absolute value function and the modulus operator to generate integers between 0 and 99.

// There is a 5% chance of signal loss.
module randloss (pinout) ;
electrical pinout ;
integer randseed, randnum;
analog begin
    @ (initial_step) begin
        randseed = 123 ;    // Initialize the seed just once
    end
    randnum = abs($random(randseed) % 100) ;
    if (randnum < 5) 
     V(pinout) <+ 0.0 ;
else
V(pinout) <+ 3.0 ;
end // of analog block
endmodule

Generating Random Numbers in Specified Distributions

Verilog-AMS provides functions that generate random numbers in the following distribution patterns:

In releases prior to IC5.0, the functions beginning with $dist return real numbers rather than integer numbers. If you need to continue getting real numbers in more recent releases, change each $dist function to the corresponding $rdist function.

Uniform Distribution

Use the $rdist_uniform function to generate random real numbers (or the $dist_uniform function to generate integer numbers) that are evenly distributed throughout a specified range. The $rdist_uniform function is not supported in digital contexts.

$rdist_uniform ( seed , start , end ) ;
$dist_uniform
( seed , start , end ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of a uniform distribution, change the value of seed only when you initialize the sequence.

start is an integer or real expression that specifies the smallest number that the $dist_uniform function is allowed to return. start must be smaller than end.

end is an integer or real expression that specifies the largest number that the $dist_uniform function is allowed to return. end must be larger than start.

The following module returns a series of real numbers, each of which is between 20 and 60 inclusively.

module distcheck (pinout) ;
electrical pinout ;
parameter integer start_range = 20 ; // A parameter
integer seed, end_range;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;                        // Initialize the seed just once
        end_range = 60 ;                   // A variable
    end
    rrandnum = $rdist_uniform(seed, start_range, end_range);
    $display ("Random number is %g", rrandnum ) ;
// The next line shows how the seed changes at each
// iterative use of the distribution function.
 $display ("Current seed is %d", seed) ;
 V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Normal (Gaussian) Distribution

Use the $rdist_normal function to generate random real numbers (or the $dist_normal function to generate integer numbers) that are normally distributed. The $rdist_normal function is not supported in digital contexts.

$rdist_normal ( seed , mean , standard_deviation ) ;
$dist_normal
( seed , mean , standard_deviation ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of a normal distribution, change the value of seed only when you initialize the sequence.

mean is an integer or real expression that specifies the value to be approached by the mean value of the generated numbers.

standard_deviation is an integer or real expression that determines the width of spread of the generated values around mean. Using a larger standard_deviation spreads the generated values over a wider range.

To generate a gaussian distribution, use a mean of 0 and a standard_deviation of 1. For example, the following module returns a series of real numbers that together form a gaussian distribution.

module distcheck (pinout) ;
electrical pinout ;
integer seed ;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;
    end 
    rrandnum = $rdist_normal( seed, 0, 1 ) ;
    $display ("Random number is %g", rrandnum ) ;
    V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Exponential Distribution

Use the $rdist_exponential function to generate random real numbers (or the $dist_exponential function to generate integer numbers) that are exponentially distributed. The $rdist_exponential function is not supported in digital contexts.

$rdist_exponential ( seed , mean ) ;
$dist_exponential
( seed , mean ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of an exponential distribution, change the value of seed only when you initialize the sequence.

mean is an integer or real value greater than zero. mean specifies the value to be approached by the mean value of the generated numbers.

For example, the following module returns a series of real numbers that together form an exponential distribution.

module distcheck (pinout) ;
electrical pinout ;
integer seed, mean ;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;
        mean = 5 ;              // Mean must be > 0
    end 
    rrandnum = $rdist_exponential(seed, mean) ;
    $display ("Random number is %g", rrandnum ) ;
    V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Poisson Distribution

Use the $rdist_poisson function to generate random real numbers (or the $dist_poisson function to generate integer numbers) that form a Poisson distribution. The $rdist_poisson function is not supported in digital contexts.

$rdist_poisson ( seed , mean ) ;
$dist_poisson
( seed , mean ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of a Poisson distribution, change the value of seed only when you initialize the sequence.

mean is an integer or real value greater than zero. mean specifies the value to be approached by the mean value of the generated numbers.

For example, the following module returns a series of real numbers that together form a Poisson distribution.

module distcheck (pinout) ;
electrical pinout ;
integer seed, mean ;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;
        mean = 5 ;                    // Mean must be > 0
    end 
    rrandnum = $rdist_poisson(seed, mean) ;
    $display ("Random number is %g", rrandnum ) ;
    V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Chi-Square Distribution

Use the $rdist_chi_square function to generate random real numbers (or the $dist_chi_square function to generate integer numbers) that form a chi-square distribution. The $rdist_chi_square function is not supported in digital contexts.

$rdist_chi_square ( seed , degree_of_freedom ) ;
$dist_chi_square
( seed , degree_of_freedom ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of a chi-square distribution, change the value of seed only when you initialize the sequence.

degree_of_freedom is an integer value greater than zero. degree_of_freedom determines the width of spread of the generated values. Using a larger degree_of_freedom spreads the generated values over a wider range.

For example, the following module returns a series of real numbers that together form a chi-square distribution.

module distcheck (pinout) ;
electrical pinout ;
integer seed, dof ;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;
        dof = 5 ;           // Degree of freedom must be > 0
    end 
    rrandnum = $rdist_chi_square(seed, dof) ;
    $display ("Random number is %g", rrandnum ) ;
    V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Student’s T Distribution

Use the $rdist_t function to generate random real numbers (or the $dist_t function to generate integer numbers) that form a Student’s T distribution. The $rdist_t function is not supported in digital contexts.

$rdist_t ( seed , degree_of_freedom ) ;
$dist_t
( seed , degree_of_freedom ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of a Student’s T distribution, change the value of seed only when you initialize the sequence.

degree_of_freedom is an integer value greater than zero. degree_of_freedom determines the width of spread of the generated values. Using a larger degree_of_freedom spreads the generated values over a wider range.

For example, the following module returns a series of real numbers that together form a Student’s T distribution.

module distcheck (pinout) ;
electrical pinout ;
integer seed, dof ;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;
        dof = 15 ; // Degree of freedom must be > 0
    end 
    rrandnum = $rdist_t(seed, dof) ;
    $display ("Random number is %g", rrandnum ) ;
    V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Erlang Distribution

Use the $rdist_erlang function to generate random real numbers (or the $dist_erlang function to generate integer numbers) that form an Erlang distribution. The $rdist_erlang function is not supported in digital contexts.

$rdist_erlang ( seed , k , mean ) ;
$dist_erlang
( seed , k , mean ) ;

seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of an Erlang distribution, change the value of seed only when you initialize the sequence.

k is an integer value greater than zero. Using a larger value for k decreases the variance of the distribution.

mean is an integer or real value greater than zero. mean specifies the value to be approached by the mean value of the generated numbers.

For example, the following module returns a series of real numbers that together form an Erlang distribution.

module distcheck (pinout) ;
electrical pinout ;
integer seed, k, mean ;
real rrandnum ;
analog begin
    @ (initial_step) begin
        seed = 23 ;
        k = 20 ;                // k must be > 0
        mean = 15 ;             // Mean must be > 0
    end 
    rrandnum = $rdist_erlang(seed, k, mean) ;
    $display ("Random number is %g", rrandnum ) ;
    V(pinout) <+ rrandnum ;
end // of analog block
endmodule

Interpolating with Table Models

Use the $table_model function to model the behavior of a design by interpolating between and extrapolating outside of data points.

table_model_declaration ::=
    $table_model(variables , table_source [ , ctrl_string ] )
variables ::=
        independent_var { , 2nd_independent_var [ , nth_independent_var ]}
table_source ::=
        data_file
    |   table_model_array
data_file ::=
        "filename"
    |   string_param
table_model_array ::=
        array_ID { , 2nd_array_ID [ , nth_array_ID ]}, output_array_ID
ctrl_string ::=
        "sub_ctrl_string [ , sub_ctrl_string ][; dependent_selector ]"
sub_ctrl_string ::=
     I
| D
| [ degree_char ] [ extrap_char [ extrap_char ]]
degree_char ::=
        1 | 2 | 3
extrap_char ::=
        C | L | S | E
dependent_selector ::=
    positive_integer_number

independent_var is an independent model variable. An independent_var can be any legal numerical expression that you can assign to an analog signal. You must specify an independent model variable for each dimension with a corresponding sub_ctrl_string other than I (ignore). You must not specify an independent model variable for dimensions that have a sub_ctrl_string of I (ignore).

The I (ignore) sub_ctrl_string and support for more than one dimension are extensions beyond the Verilog-AMS LRM, Version 2.2.

data_file is the text file that stores the sample points. You can either give the file name directly or use a string parameter. For more information, see “Table Model File Format”.

table_model_array is a set of one-dimensional arrays that contains the data points to pass to the $table_model function. The size of the arrays is the same as the number of sample points. The data is stored in the arrays so that for the kth dimension of the ith sample point, kth_dim_array_identifier[i] = Xik and so that for the ith sample point output_array_identifier[i] = Yi. For an example, see “Example: Preparing Data in One-Dimensional Array Format”.

ctrl_string controls the numerical aspects of the interpolation process. It consists of subcontrol strings for each dimension.

sub_ctrl_string specifies the handling for each dimension.

When you specify I (ignore), the software ignores the corresponding dimension (column) in the data file. You might use this setting to skip over index numbers, for example. When you associate the I (ignore) value with a dimension, you must not specify a corresponding independent_var for that dimension.

When you specify D (discrete), the software does not use interpolation for this dimension. If the software cannot find the exact value for the dimension in the corresponding dimension in the data file, it issues an error message and the simulation stops.

degree_char is the degree of the splines used for interpolation. The degree can be 1 (linear interpolation), 2 (quadratic spline interpolation), and 3 (cubic spline interpolation). The default value is 1.

extrap_char controls how the simulator evaluates a point that is outside the region of sample points included in the data file. The C (clamp) extrapolation method uses a horizontal line that passes through the nearest sample point, also called the end point, to extend the model evaluation. The L (linear) extrapolation method, which is the default method, models the extrapolation through a tangent line at the end point. The S (spline) extrapolation method uses the polynomial for the nearest segment (the segment at the end) to evaluate a point beyond the interpolation area. The E (error) extrapolation method issues a warning when the point to be evaluated is beyond the interpolation area.

You can specify the extrapolation method to be used for each end of the sample point region. When you do not specify an extrap_char value, the linear extrapolation method is used for both ends. When you specify only one extrap_char value, the specified extrapolation method is used for both ends. When you specify two extrap_char values, the first character specifies the extrapolation method for the end with the smaller coordinate value, and the second character specifies the method for the end with the larger coordinate value.

dependent_selector enables you to select the dependent column in the table that needs to be interpolated. Multiple dependent variables are supported. For example, in the table control string ‘I,1L;3’, 3 is the dependent selector. This means that:

You can use the $table_model function in the analog context (in an analog block) and in the digital context (such as in an initial or an always block). In the analog context, the $table_model function is subject to the same restrictions as analog operators with respect to where you can use the function. For more information, see “Restrictions on Using Analog Operators”.

In digital context, you can use an environment variable to specify the location of the table file. For example:

initial begin
  out1 = $table_model(wb,"$WORKAREA/$FILENAME", "");
end

You can also specify a real model table array in a digital block. For example:

real tvar1[0:50];
real ftyp[0:50]; 
always @ (en) begin 
  test_out_real = $table_model(w_t_in , tvar1, ftyp,"3CC"); 
end
To use the $table_model function in a digital context, you must be using digital mixed-signal licensing or Spectre AMS Designer simulator licensing.

See also

Table Model File Format

The data in the table model file must be in the form of a family of ordered isolines. An isoline is a curve of at least two values generated when one variable is swept and all other variables are held constant. An ordered isoline is an isoline in which the sweeping variable is either monotonically increasing or monotonically decreasing. A monotonically increasing variable is one in which every subsequent value is equal to or greater than the previous value. A monotonically decreasing variable is one in which every subsequent value is equal to or less than the previous value.

For example, a bipolar transistor can be described by a family of isolines, where each isoline is generated by holding the base current constant and sweeping the collector voltage from 0 to some maximum voltage. If the collector voltage sweeps monotonically, the generated isoline is an ordered isoline. In this example, the collector voltage takes many values for each of the isolines so the voltage is the fastest changing independent variable and the base current is the slowest changing independent variable. You need to know the fastest changing and slowest changing independent variables to arrange the data correctly in the table model file.

The sample points are stored in the file in the following format:

P1
P2
P3
...
PM

where Pi (i = 1...M) are the sample points. Each sample point Pi is on a separate line and is represented as a sequence of numbers, Xi1 Xi2 ..Xik... XiN Yi where N is the highest dimension of the model. Xik is the coordinate of the sample point in the kth dimension, and Yi is the model value at this point. Xi1 (the leftmost variable) must be the slowest changing variable and XiN (the rightmost variable other than the model value) must be the fastest changing variable. The other variables must be arranged in between from slowest changing to fastest changing. Comments, which begin with #, can be inserted at any place in the file and can continue to the end of the line.

For example, to create a table model with three ordered isolines representing the function

z = f(x,y) = x+y2

build the model as follows, assuming that you want to have four sample values on each isoline. The y values used here are all the same and equally spaced on each isoline, but they do not have to be.

Isoline 1: x=1

y = 1, 2, 3, 4
z = 2, 5, 10, 17

Isoline 2: x=2

y = 1, 2, 3, 4
z = 3, 6, 11, 18

Isoline 3: x=3

y = 1, 2, 3, 4
z = 4, 7, 12, 19

Finally, prefix each row with an index. The function will be specified to ignore this new column of data.

Enter the table model data into the file as follows:

# Indx is the index column to be ignored.
# x is the slowest changing independent variable.
# y is the fastest changing independent variable.
# z is the table model value at each point.
# Indx x y z
1 1 1 2
2 1 2 5
3 1 3 10
4 1 4 17
5 2 1 3
6 2 2 6
7 2 3 11
8 2 4 18
9 3 1 4
10 3 2 7
11 3 3 12
12 3 4 19

Example: Using the $table_model Function

For example, assume that you have a data file named nmos.tbl, which contains the data given above. You might use it in a module as follows:

‘include "disciplines.vams"
‘include "constants.vams"

module mynmos (g, d, s);
electrical g, d, s;
inout g, d, s;

analog begin
    I(d, s) <+ $table_model (V(g, s), V(d, s), "nmos.tbl", "I,3CL,3CL");
end
endmodule

In this example, the program ignores the first column of data. The independent variables are V(g,s) and V(d,s). The degree of the splines that the program uses for interpolation is three for each of the two active dimensions. For each of these dimensions, the extrapolation method for the lower end is clamping and the extrapolation for the upper end is linear.

When table_model is used in a digital context, $table_model does not support quadratic spline interpolation. The simulator uses linear spline interpolation instead.

Example: Preparing Data in One-Dimensional Array Format

In this example, there are 18 sample points. Consequently, each of the one-dimensional arrays contains 18 bits. Each point has two independent variables, represented by x and y, and a value, represented by f_xy.

module measured_resistance (a, b);
electrical a, b;
inout a, b;
real x[0:17], y[0:17], f_xy[0:17];
analog begin
    @(initial_step) begin
        x[0]= -10; y[0]=-10; f_xy[0]=0; // 0th sample point
        x[1]= -10; y[1]=-8; f_xy[1]=-0.4; // 1st sample point
        x[2]= -10; y[2]=-6; f_xy[2]=-0.8; // 2nd sample point
        x[3]= -9; y[3]=-10; f_xy[3]=0.2;
        x[4]= -9; y[4]=-8; f_xy[4]=-0.2;
        x[5]= -9; y[5]=-6; f_xy[5]=-0.6;
        x[6]= -9; y[6]=-4; f_xy[6]=-1;
        x[7]= -8; y[7]=-10; f_xy[7]=0.4;
        x[8]= -8; y[8]=-9; f_xy[8]=0.2;
        x[9]= -8; y[9]=-7; f_xy[9]=-0.2;
        x[10]= -8; y[10]=-5; f_xy[10]=-0.6;
        x[11]= -8; y[11]=-3; f_xy[11]=-1;
        x[12]= -7; y[12]=-10; f_xy[12]=0.6;
        x[13]= -7; y[13]=-9; f_xy[13]=0.4;
        x[14]= -7; y[14]=-8; f_xy[14]=0.2;
        x[15]= -7; y[15]=-7; f_xy[15]=0;
        x[16]= -7; y[16]=-6; f_xy[16]=-0.2;
        x[17]= -7; y[17]=-5; f_xy[17]=-0.4;
    end
    I(a, b) <+ $table_model (V(a), V(b), x, y, f_xy, "3L,1L");
end
endmodule

Example: Using $table_model as a Built-In Digital System Task

You can use the $table_model function as a built-in digital system task in an initial or always block, such as:

module example(rout, rin1, rin2, clk);
wreal rout, rin1, rin2;
input rin1, rin2;
output rout;
wire clk;
input clk;
real out; assign rout = out; always @clk begin    out = $table_model(rin1, rin2,"sample.dat");
end
endmodule

Node/Net Aliasing System Functions

You can use the $analog_node_alias() system function to alias a local node to a hierarchical node through a string reference within connect modules and regular modules. In addition, you can use the Cadence proprietary system function $real_net_alias() to alias a local net to a hierarchical net through a string reference within connect modules and regular modules.

Aliasing Local Nodes to Hierarchical Nodes with $analog_node_alias

Use the $analog_node_alias system function to alias a local node to a hierarchical node through a string reference within connect modules and regular modules.

analog_node_alias_system_function ::=
 $analog_node_alias ( analog_net_reference , hierarchical_reference_string )

analog_net_reference is a node that is declared in the module containing the system function call and can be either a scalar node or a vector continuous node. In case of vector node, it references the full vector node and cannot be a bit-select or part-select of the vector node. In addition, analog_net_reference cannot be a port or part of port connections.

hierarchical_reference_string can be a string literal or a string parameter containing hierarchical reference to the continuous node. hierarchical_reference_string cannot reference a node that is used as analog_net_reference in another $analog_node_alias system function.

The $analog_node_alias system function returns 1 if hierarchical_reference_string points to a valid continuous node and aliases the analog_net_reference to the hierarchical node.

When both analog_net_reference and hierarchical_reference_string are electrical bus, each bit of the 1st argument connects to each of the 2nd argument.

The following rules determine whether a node is valid:

If the system function returns zero (0), the node referenced by analog_net_reference is treated as a normal continuous node declared in the module containing the system function call.

If a particular node is involved in multiple calls to the system function, then the last evaluated call takes precedence.

The $analog_node_alias system function can only be used within an analog initial block. In general, the $analog_node_alias system function cannot be used inside a conditional statement. However, it can be used in a conditional statement if the conditional expression controlling the statement consists of terms that do not change during the simulation.

The following is an example of the $analog_node_alias system function:

connectmodule elect_to_logic(el, cm);
    input el;
    output cm;
    reg cm;
    electrical el;
    ddiscrete cm;
    electrical vdd, vss;
    parameter string vddname = "(not_given)"; // Set via the CR
    parameter string vssname = "(not given)"; // Set via the CR
 
 analog initial begin
    if ($analog_node_alias(vdd, vddname) == 0)
       $display("Unable to resolve power supply: %s", vddname);
    if ($analog_node_alias(vss, vssname) == 0)
       $display("Unable to resolve ground: %s", vssname);
 end
  
 always @(cross(V(el) - V(vdd)/2.0, 1))
        cm = 1;
 always @(cross(V(el) - V(vdd)/2.0, -1))
        cm = 0;
 
 endmodule
 
connectmodule logic_to_elect(cm, el);
    input cm;
    output el;
    ddiscrete cm;
    electrical el;
    electrical vdd, vss;
    parameter string vddname = "(not_given)"; // Set via the CR
    parameter string vssname = "(not given)"; // Set via the CR
 
 analog initial begin
    if ($analog_node_alias(vdd, vddname) == 0)
       $error("Unable to resolve power supply: %s", vddname);
    if ($analog_node_alias(vss, vssname) == 0)
       $error("Unable to resolve ground: %s", vssname);
 end
 
 analog V(el) <+ V(vdd) * transition((cm == 1) ? 1 : 0);
 
endmodule

Aliasing Local Nets to Hierarchical Nets with $real_net_alias

Use the $real_net_alias Cadence proprietary system function to alias a local net to a hierarchical net through a string reference within connect modules and regular modules.

real_net_alias_system_function ::=
 $real_net_alias ( real_net_reference , hierarchical_reference_string )

Here, real_net_reference is a net that is declared in the module containing the system function call. The local net can be a local scalar, a vector wreal net, a wreal array, or SV-UDN real net array. If real_net_reference is a vector, it references the full vector. Part-select or bit-select of array is not supported.

hierarchical_reference_string can be a string literal or a string parameter containing hierarchical reference to the wreal net, a scalar element of a vector wreal net, a wreal array, SV-UDN real net array. The array reference can be bit-select or part-select. hierarchical_reference_string should refer to a scalar wreal net or a scalar element of a wreal net. In bit select array reference, the index must be an integer constant value.

In SV-UDN real net array connections, both the real_net_reference and hierarchical_reference_string arguments must be of the same nettype. And, the $real_net_alias system function does not support SV-UDN nets with struct type; and, returns zero value in this case.

When both the real_net_reference and hierarchical_reference_string arguments are arrays, each bit of the first argument connects to each of the second argument. When real_net_reference is array and hierarchical_reference_string is scalar or bit-select, each bit of the array connects to the scalar or bit-select. And, when the hierarchical_reference_string is array, the width of both arguments should be identical.

The $real_net_alias system function returns 1 if hierarchical_reference_string points to a valid discrete wreal net and returns zero (0) otherwise. If the return value is 1, then the real_net_reference is aliased to that hierarchical net. If the system function returns zero (0), then the net referenced by real_net_reference is treated as a normal local wreal net declared in the module containing the system function call.

If a particular net is involved in multiple calls to the system function, then the last evaluated call (in the module context) takes precedence.

The $real_net_alias system function can only be used in a digital block. You can use the $real_net_alias system function in both connect modules and Verilog-AMS modules.

The following example shows the usage of the $real_net_alias system function in a Verilog-AMS connect module:

module top;
    wreal a, b;
    reg r1, r2, r3, r4;
    foo f1();
    parameter string p = "top.f1.y";
    initial begin
        r1 = $real_net_alias(a, "top.f1.x");    // #1, valid, but this does not                                                      take effect because of #4 below
        if (r1) $display("top.f1.x is legal "); // #2, $display works
    end
    initial begin
        #0;
        $display("a = ", a);                    // #3, wreal net 'a' get assigned                                                 at time zero
        #3;
        r2 = $real_net_alias(a, p);             // #4, this is the last valid func-                                               call for 'a'
        $display("a = ", a,,r2,,top.f1.y,,b);   // #5
        #3;
        r3 = $real_net_alias(a, "top.f1.no");   // #6, invalid, this function call                                                does not work, r3 = 0
        r4 = $real_net_alias(b, "top.f1.y");    // #7, valid, this takes effect and                                               result is shown in #5 above
    end
endmodule
module foo;
    wreal x, y;
    assign x = 1.11;
    assign y = 5.43;
endmodule
 
Simulation outputs:
top.f1.x is legal
a = 5.43
a = 5.43 1 5.43 5.43

The following example shows the usage of the $real_net_alias function in a dynamic supply connect module:

connectrules ddiscrete_dynsup_full_fast_cr;
    connect L2R_dynsup #(.vddname("top.f1.a"), .vssname("top.f1.x")) ;
    ......
endconnectrules
`timescale 1ns / 1ps
connectmodule L2R_dynsup(Rout, Lin);
   input Lin;
   output  Rout; wreal Rout;
   wreal vss, vdd;
   parameter string vddname = "(no value)";
   parameter string vssname = "(no value)";
   parameter real vsup_min=0.5 from (0:inf); // min supply for normal operation
   parameter real vlo = 0;                   // logic low voltage
   reg supOK;
   real L_conv, v_vdd, v_vss;
   initial begin
      L_conv = `wrealZState;
      v_vdd = $real_net_alias(vdd, vddname); 
      v_vss = $real_net_alias(vss, vssname);
      if (!v_vss || !v_vdd) begin   
         $display("==== Invalid Parameter(s) at %m: vddname=", vddname,,"vssname=", vssname); 
         $finish;
      end  
      else  
         $display("==== Valid Parameter(s) at %m: vddname=", vddname,,"vssname=", vssname);
   end
   always begin
      if ( vdd - vss > vsup_min)
         supOK = 1'b1; 
      else
         supOK = 1'b0;
      @(vdd, vss);
   end
   // Determine the value of L and convert to a real value
   always begin
      if ( supOK ) begin
         case (Lin)
          1'b0:
             L_conv = vss;
          1'b1:
            L_conv = vdd;
          1'bz:
            L_conv = `wrealZState;
          default:
            L_conv = `wrealXState;
         endcase
       end
      else
         L_conv = `wrealXState;
      @(Lin, supOK, vss, vdd);
   end
   // drive the converted value back onto the output R pin
   assign Rout = L_conv;
endmodule

Limitations

Analog Operators

Analog operators are functions that operate on more than just the current value of their arguments. These functions maintain an internal state and produce a return value that is a function of an input expression, the arguments, and their internal state.

The analog operators are the

Restrictions on Using Analog Operators

Analog operators are subject to these restrictions:

Limited Exponential Function

Use the limited exponential function to calculate the exponential of a real argument.

limexp( expr )

expr is a dynamic expression of type real.

The limexp function limits the iteration step size to improve convergence. limexp behaves like the exp function, except that using limexp to model semiconductor junctions generally results in dramatically improved convergence. For information on the exp function, see “Standard Mathematical Functions”.

The limexp function is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

Time Derivative Operator

Use the time derivative operator to calculate the time derivative of an argument.

ddt( input [ , abstol | nature ] )

input is a dynamic expression.

abstol is a constant specifying the absolute tolerance that applies to the output of the ddt operator. Set abstol at the largest signal level that you consider negligible. In this release of Verilog-AMS, abstol is ignored.

nature is a nature from which the absolute tolerance is to be derived. In this release of Verilog-AMS, nature is ignored.

The time derivative operator is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

In DC analyses, the ddt operator returns 0. To define a higher order derivative, you must use an internal node or signal. For example, a statement such as the following is illegal.

V(out) <+ ddt(ddt(V(in))) // ILLEGAL!

For an example illustrating how to define higher order derivatives correctly, see “Using Integration and Differentiation with Analog Signals”.

You cannot output the result of the ddt operator using statements such as $print, $strobe, and $fopen. Instead, you can use an internal node to record the value, then output the value of the internal node.

Time Integral Operator

Use the time integral operator to calculate the time integral of an argument.

idt( input [ , ic [ , assert [ , abstol | nature ] ] ] )

input is a dynamic expression to be integrated.

ic is a dynamic expression specifying the initial condition.

assert is a dynamic integer-valued parameter. To reset the integration, set assert to a nonzero value.

abstol is a constant explicit absolute tolerance that applies to the input of the idt operator. Set abstol at the largest signal level that you consider negligible.

nature is a nature from which the absolute tolerance is to be derived.

The time integral operator is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

The value returned by the idt operator during DC or AC analysis depends on which of the parameters you specify.

If you specify Then idt returns

input

The time-integral of x from 0 to t with the initial condition being computed in the DC analysis.

input, ic

The time-integral of x from 0 to t with initial condition ic. In DC or IC analyses, returns ic.

input, ic, assert

The time-integral of x from t 0 to t with initial condition ic. In DC or IC analyses, and when assert is nonzero, returns ic. t0 is the time when assert last became 0.

input, ic, assert, abstol

The time-integral of x from t 0 to t with initial condition ic. In DC or IC analysis, and when assert is nonzero, returns ic. t0 is the time when assert last became 0.

input, ic, assert, nature

The time-integral of x from t 0 to t with initial condition ic. In DC or IC analysis, and when assert is nonzero, returns ic. t0 is the time when assert last became 0.

The initial condition forces the DC solution to the system. You must specify the initial condition, ic, unless you are using the idt operator in a system with feedback that forces input to zero. If you use a model in a feedback configuration, you can leave out the initial condition 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 that forced DC solution.

The following statement illustrates using idt with a specified initial condition.

V(out) <+ sin(2*`M_PI*(fc*$abstime + idt(gain*V(in),0))) ;

Circular Integrator Operator

Use the circular integrator operator to convert an expression argument into its indefinitely integrated form.

idtmod(expr [ , ic [ , modulus [, offset [, abstol | nature ] ] ] ] )

expr is the dynamic integrand or expression to be integrated.

ic is a dynamic initial condition. By default, the value of ic is zero.

modulus is a dynamic value at which the output of idtmod is reset. modulus must be a positive value equation. If you do not specify modulus, idtmod behaves like the idt operator and performs no limiting on the output of the integrator.

offset is a dynamic value added to the integration. The default is zero.

The modulus and offset parameters define the bounds of the integral. The output of the idtmod function always remains in the range

offset < idtmod_output < offset+modulus

abstol is a constant explicit absolute tolerance that applies to the input of the idtmod operator. Set abstol at the largest signal level that you consider negligible.

nature is a nature from which the absolute tolerance is to be derived.

The circular integrator operator is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

The value returned by the idtmod operator depends on which parameters you specify.

If you specify Then idtmod returns

expr

The time-integral of expr from 0 to t with the initial condition being computed in the DC analysis. Returns x.

expr, ic

The time-integral of expr from 0 to t with initial condition ic. In DC or IC analysis, returns ic; otherwise, returns x.

expr, ic, modulus

where x = n*modulus + k
n
= ... -3, -2, -1, 0, 1, 2, 3 ...
Returns k where 0 < k < modulus

expr, ic, modulus, offset

where x = n*modulus + k
Returns k where offset < k < offset + modulus

expr, ic, modulus, offset, abstol

where x = n*modulus + k
Returns k where offset < k < offset + modulus

expr, ic, modulus, offset, nature

where x = n*modulus + k
Returns k where offset < k < offset + modulus

The initial condition forces the DC solution to the system. You must specify the initial condition, ic, unless you are using idtmod in a system with feedback that forces expr to zero. If you use a model in a feedback configuration, you can leave out the initial condition without any unexpected behavior during simulation.

Example

The circular integrator is useful in cases where the integral can get very large, such as in a voltage controlled oscillator (VCO). For example, you might use the following approach to generate arguments in the range [0,2π] for the sinusoid.

phase = idtmod(fc + gain*V(IN), 0, 1, 0); //Phase is in range [0,1].
V(OUT) <+ sin(2*PI*phase);

Derivative Operator

Use the ddx operator to access symbolically-computed partial derivatives of expressions in the analog block.

ddx (expr, potential_access_id (net_or_port_scalar_expr))
ddx (
expr, flow_access_id (branch_id))

expr is a real or integer value expression. The derivative operator returns the partial derivative of this argument with respect to the unknown indicated by the second argument, with all other unknowns held constant and evaluated at the current operating point. If expr does not depend explicitly on the unknown, the derivative operator returns zero. The expr argument:

potential_access_id is the access operator for the potential of a scalar net or port.

net_or_port_scalar_expr is a scalar net or port.

flow_access_id is the access operator for the flow through a branch.

branch_id is the name of a branch.

The derivative operator is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

Example

This example implements a voltage-controlled dependent current source. The names of the variables indicate the values of the partial derivatives: +1, -1, or 0. These values (scaled by the parameter k) can be used in a Newton-Raphson solution.

module vccs(pout,nout,pin,nin);
    electrical pout, nout, pin, nin;
    inout pout, nout, pin, nin;
    parameter real k = 1.0;
    real vin, one, minusone, zero;
    analog begin
     vin = V(pin,nin);
one = ddx(vin, V(pin));
minusone = ddx(vin, V(nin));
zero = ddx(vin, V(pout));
I(pout,nout) <+ k * vin;
end
endmodule

Delay Operator

Use the absdelay operator to delay the entire signal of a continuously valued waveform.

absdelay( expr , time_delay [ , max_delay ] )

expr is a dynamic expression to be delayed.

time_delay, a dynamic nonnegative value, is the length of the delay. If you specify max_delay, you can change the value of time_delay during a simulation, as long as the value remains in the range 0 < time_delay < max_delay. Typically time_delay is a constant but can also vary with time (when max_delay is defined).

max_delay is a constant nonnegative number greater than or equal to time_delay. You cannot change max_delay because the simulator ignores any attempted changes and continues to use the initial value.

For example, to delay an input voltage you might code

V(out) <+ absdelay(V(in), 5u) ;

The absdelay operator is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

In DC and operating analyses, the absdelay operator returns the value of expr unchanged. In time-domain analyses, the absdelay operator introduces a transport delay equal to the instantaneous value of time_delay based on the following formula.

Output(t) = Input(max(t-time_delay, 0))

Transition Filter

Use the transition filter to smooth piecewise constant waveforms, such as digital logic waveforms. The transition filter returns a real number that over time describes a piecewise linear waveform. The transition filter also causes the simulator to place time points at both corners of a transition to assure that each transition is adequately resolved.

transition(input [, delay [, rise_time [, fall_time [, time_tol ]]]])

input is a dynamic input expression that describes a piecewise constant waveform. It must have a real value. In DC analysis, the transition filter simply returns the value of input. Changes in input do not have an effect on the output value until delay seconds have passed.

delay is a dynamic nonnegative real value that is an initial delay. By default, delay has a value of zero.

rise_time is a dynamic positive real value specifying the time over which you want positive transitions to occur. If you do not specify rise_time or if you give rise_time a value of 0, rise_time defaults to the value defined by ‘default_transition.

fall_time is a dynamic positive real number specifying the time over which you want negative transitions to occur. By default, fall_time has the same value that rise_time has. If you do not specify rise_time or if you give rise_time a value of 0, fall_time defaults to the value defined by ‘default_transition.

time_tol is a constant expression with a positive value. This option requires the simulator to place time points no more than the value of time_tol away from the two corners of the transition.

If ‘default_transition is not specified, the default behavior of the transition filter approximates the ideal behavior of a zero-duration transition.

The transition filter is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

With the transition filter, you can control transitions between discrete signal levels by setting the rise time and fall time of signal transitions. The transition filter stretches instantaneous changes in signals over a finite amount of time, as shown below, and can also delay the transitions.

Use short transitions with caution because they can cause the simulator to slow down to meet accuracy constraints.

The next code fragment demonstrates how the transition filter might be used.

// comparator model
analog begin
    if ( V(in) > 0 ) begin
        Vout = 5 ;
        end 
    else begin
        Vout = 0 ;
    end
    V(out) <+ transition(Vout) ;
end
The transition filter is designed to smooth out piecewise constant waveforms. If you apply the transition filter to smoothly varying waveforms, the simulator might run slowly, and the results will probably be unsatisfactory. For smoothly varying waveforms, consider using the slew filter instead. For information, see “Slew Filter”.

If interrupted on a rising transition, the transition filter adjusts the slope so that at the revised end of the transition the value is that of the new destination.

If the new destination value is below the value at the point of interruption, the transition filter If the new destination value is above the value at the point of interruption, the transition filter
  1. Uses the value of the original destination as the value of the new origin.
  2. Adjusts the slope of the transition to the rate at which the value would decay from the value of the new origin to the value of the new destination in fall_time seconds.
  3. Causes the value of the filter output to decay at the new slope, from the value at the point of interruption to the value at the new destination.
  1. Retains the original origin.
  2. Adjusts the slope of the transition to the rate at which the value would increase from the value of the origin to the value of the new destination in rise_time seconds.
  3. Causes the value of the filter output to increase at the new slope, from the value at the point of interruption to the value at the new destination.

In the following example, a rising transition is interrupted when it is about three fourths complete, and the value of the new destination is below the value at the point of interruption. The transition filter computes the slope that would complete a transition from the new origin (not the value at the point of interruption) in the specified fall_time. The transition filter then uses the computed slope to transition from the current value to the new destination.

An interruption in a falling transition causes the transition filter to behave in an equivalent manner.

With larger delays, it is possible for a new transition to be specified before a previously specified transition starts. The transition filter handles this by deleting any transitions that would follow a newly scheduled transition. A transition filter can have an arbitrary number of transitions pending. You can use a transition filter in this way to implement the transport delay of discretely valued signals.

The following example implements a D-type flip flop. The transition filter smooths the output waveforms.

module d_ff(vin_d, vclk, vout_q, vout_qbar) ;
input vclk, vin_d ;
output vout_q, vout_qbar ;
electrical vout_q, vout_qbar, vclk, vin_d ;
parameter real vlogic_high = 5 ;
parameter real vlogic_low = 0 ;
parameter real vtrans_clk = 2.5 ;
parameter real vtrans = 2.5 ;
parameter real tdel = 3u from [0:inf) ;
parameter real trise = 1u from (0:inf) ;
parameter real tfall = 1u from (0:inf) ;
integer x ;
analog begin
    @ (cross( V(vclk) - vtrans_clk, +1 )) x = (V(vin_d) > vtrans) ;
    V(vout_q) <+ transition( vlogic_high*x + vlogic_low*!x,tdel, trise, tfall );
    V(vout_qbar) <+ transition( vlogic_high*!x + vlogic_low*x, tdel, 
                                                    trise, tfall ) ;
    end
endmodule

The following example illustrates a use of the transition filter that should be avoided. The expression is dependent on a continuous signal and, as a consequence, the filter runs slowly.

I(p, n) <+ transition(V(p, n)/out1, tdel, trise, tfall);     // Do not do this.

However, you can use the following approach to implement the same behavior in a statement that runs much faster.

I(p, n) <+ V(p, n) * transition(1/out1, tdel, trise, tfall); // Do this instead.

Slew Filter

Use the slew filter to control the rate of change of a waveform. A typical use for slew is generating continuous signals from piecewise continuous signals. For discrete signals, consider using the transition filter instead. See “Transition Filter” for more information.

slew(input [ , max_pos_rate [ , max_neg_rate ] ] )

input is a dynamic expression with a real value. In DC analysis, the slew filter simply returns the value of input.

max_pos_rate is a dynamic real number greater than zero, which is the maximum positive slew rate.

max_neg_rate is a dynamic real number less than zero, which is the maximum negative slew rate.

If you specify only one rate, its absolute value is used for both rates. If you give no rates, slew passes the signal through unchanged. If the rate of change of input is less than the specified maximum slew rates, slew returns the value of input.

The slew filter is subject to the restrictions listed in “Restrictions on Using Analog Operators”.

When applied, slew forces all transitions of expr faster than max_pos_rate to change at the max_pos_rate rate for positive transitions and limits negative transitions to the max_neg_rate rate.

The slew filter is particularly valuable for controlling the rate of change of sinusoidal waveforms. The transition function distorts such signals, whereas slew preserves the general shape of the waveform. The following 4-bit digital-to-analog converter uses the slew function to control the rate of change of the analog signal at its output.

module dac4(d, out) ;
input [0:3] d ;
inout out ;
electrical [0:3] d ;
electrical out ;
parameter real slewrate = 0.1e6 from (0:inf) ;
 real Ti ; 
real Vref ;
real scale_fact ;
 analog begin 
Ti = 0 ;
Vref = 1.0 ;
scale_fact = 2 ;
generate ii (3,0,-1) begin
Ti = Ti + ((V(d[ii]) > 2.5) ? (1.0/scale_fact) : 0);
scale_fact = scale_fact/2 ;
end
V(out) <+ slew( Ti*Vref, slewrate ) ;
end
endmodule

Implementing Laplace Transform S-Domain Filters

The Laplace transform filters implement lumped linear continuous-time filters. Each filter accepts an optional absolute tolerance parameter ε, which this release of Verilog-AMS ignores. The set of array values that are used to define the poles and zeros, or numerator and denominator, of a filter the first time it is used during an analysis are used at all subsequent time points of the analysis. As a result, changing array values during an analysis has no effect on the filter.

The Laplace transform filters are subject to the restrictions listed in “Restrictions on Using Analog Operators”. However, while most analog functions can be used, with certain restrictions, in if or case constructs, the Laplace transform filters cannot be used in if or case constructs in any circumstances.

Arguments Represented as Vectors

If you use an argument represented as a vector to define a numerator in a Laplace filter, and if one or more of the elements in the vector are 0, the order of the numerator is determined by the position of the rightmost non-zero vector element. For example, in the following module, the order of the numerator, nn, is 1

module test(pin, nin, pout, nout);
electrical pin, nin, pout, nout;
real nn[0:2];
real dd[0:2];
analog begin
    @(initial_step) begin
        nn[0] = 1;// The highest order non-zero coefficient of the numerator.
        nn[1] = 0;
        nn[2] = 0;
        dd[0] = 1;
        dd[1] = 1;
        dd[2] = 1;
    end
    V(pout, nout) <+ laplace_nd(V(pin,nin), nn, dd);
end
endmodule

Arguments Represented as Arrays

If you use an argument represented as an array constant to define a numerator in a Laplace filter, and if one or more of the elements in the array constant are 0, the order of the numerator is determined by the position of the rightmost non-zero array element. For example, if your numerator array constant is {1,0,0}, the order of the numerator is 1. If your array constant is {1,0,1}, the order of the numerator is 3. In the following example, the numerator order is 1 (and the value is 1).

module test(pin, nin, pout, nout);
electrical pin, nin, pout, nout;
analog begin
    V(pout, nout) <+ laplace_nd(V(pin,nin), {1,0,0}, {1,1,1});
end
endmodule

Array literals used for the Laplace transforms can also take the form that uses a back tic. For example,

V(out) <+ laplace_nd(‘{5,6},‘{7.8,9.0});

Zero-Pole Laplace Transforms

Use laplace_zp to implement the zero-pole form of the Laplace transform filter.

laplace_zp(expr, ζ, ρ [ , ε ])

ζ (zeta) is a fixed-sized 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. ρ (rho) is a fixed-sized vector of N real pairs, one for each pole. Specify the poles in the same manner as the zeros. If you use array literals to define the ζ and ρ vectors, the values must be constant or dependent upon parameters only. You cannot use array literal values defined by variables.

The transfer function is

where and are the real and imaginary parts of the zero, and and are the real and imaginary parts of the pole.

If a root (a pole or zero) is real, you must specify the imaginary part as 0. If a root is complex, its conjugate must be present. If a root is zero, the term associated with it is implemented as s rather than , where r

Zero-Denominator Laplace Transforms

Use laplace_zd to implement the zero-denominator form of the Laplace transform filter.

laplace_zd(expr,
 
ζ, d [ , ε ])

ζ (zeta) is a fixed-sized 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. d is a fixed-sized vector of N real numbers that contains the coefficients of the denominator. If you use array literals to define the ζ and d vectors, the values must be constant or dependent upon parameters only. You cannot use array literal values defined by variables.

The transfer function is

where and are the real and imaginary parts of the zero, and is the coefficient of the power of

ss rather than .

Numerator-Pole Laplace Transforms

Use laplace_np to implement the numerator-pole form of the Laplace transform filter.

laplace_np(expr, n,
 
ρ [ , ε ])

n is a fixed-sized vector of M real numbers that contains the coefficients of the numerator. ρ (rho) is a fixed-sized 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. If you use array literals to define the n and ρ vectors, the array values must be constant or dependent upon parameters only. You cannot use array values defined by variables.

The transfer function is

where is the coefficient of the power of

s and are the real and imaginary parts of the pole. If a pole is real, you must specify the imaginary part as 0. If a pole is complex, its conjugate must be present. If a pole is zero, the term associated with it is implemented as s rather than .

Numerator-Denominator Laplace Transforms

Use laplace_nd to implement the numerator-denominator form of the Laplace transform filter.

laplace_nd(expr, n, d [ , ε ])

n is a fixed-sized vector of M real numbers that contains the coefficients of the numerator, and d is a fixed-sized vector of N real numbers that contains the coefficients of the denominator. If you use array literals to define the n and d vectors, the values must be constant or dependent upon parameters only. You cannot use array values defined by variables.

The transfer function is

where is the coefficient of the power of

s is the coefficient of the power of s in the denominator.

Examples

The following code fragments illustrate how to use the Laplace transform filters.

V(out) <+ laplace_zp(V(in), {0,0}, {1,2,1,-2});

implements

The code fragment

V(out) <+ laplace_nd(V(in), {0,1}, {1,-0.4,0.2});

is equivalent.

The following statement contains an empty vector such that the middle argument is null:

V(out) <+ laplace_zp(V(in), , {-1,0}); 

The absence of zeros, indicated by the null argument, means that the transfer function reduces to the following equation:

The next module illustrates the use of array literals that depend on parameters. In this code, the array literal {dx,6*dx,5*dx} depends on the value of the parameter dx.

module svcvs_zd(pin, nin, pout, nout);
electrical pin, nin, pout, nout;
parameter real nx = 0.5;
parameter integer dx = 1;
analog begin
    V(pout,nout) <+ laplace_zd(V(pin,nin),{0-nx,0},{dx,6*dx,5*dx});
end
endmodule

The next fragment illustrates an efficient way to initialize array values. Because only the initial set of array values used by a filter has any effect, this example shows how you can use the initial_step event to set values at the beginning of the specified analyses.

real nn[0:1] ;
real dd[0:2] ;
analog begin
    @(initial_step("static")) begin
        nn[0] = 1 ;            // These assignment
        nn[1] = 2 ;            // statements run only
        dd[0] = 1 ;            // at the beginning of
        dd[1] = 6 ;            // the analyses.
    end
    V(pout, nout) <+ laplace_nd(V(pin,nin), nn, dd) ;
end

When you use this technique, be sure to initialize the arrays at the beginning of each analysis that uses the filter.The static analysis is the dc operating point calculation required by most analyses, including tran, ac, and noise. Initializing the array during the static phase ensures that the array is non-zero as these analyses proceed.

The next modules illustrate how you can use an array variable to avoid error messages about using array literals with variable dependencies in the Laplace filters. The first version causes an error message.

// This version does not work.
‘include "constants.vams"
‘include "disciplines.vams"
module laplace(out, in);
inout in, out;
electrical in, out;
real dummy;
 analog begin
dummy = -0.5;
V(out) <+ laplace_zd(V(in), [dummy,0], [1,6,5]); //Illegal!
end
endmodule

The next version works as expected.

// This version works correctly.
‘include "constants.vams"
‘include "disciplines.vams"
module laplace(out, in);
inout in, out;
electrical in, out;
real dummy;
real nn[0:1];
analog begin
    dummy = -0.5;
    @(initial_step) begin     // Defines the array variable.
        nn[0] = dummy;
        nn[1] = 0;
    end
 V(out) <+  laplace_zd(V(in), nn, [1,6,5]);
end
endmodule

Implementing Z-Transform Filters

The Z-transform filters implement linear discrete-time filters. Each filter requires you to specify a parameter T, the sampling period of the filter. A filter with unity transfer function acts like a simple sample-and-hold that samples every T seconds.

All Z-transform filters share three common arguments, T , τ , and t0 . The T argument specifies the period of the filter and must be positive. τ specifies the transition time and must be nonnegative. If you specify a nonzero transition time, the simulator controls the time step to accurately resolve both the leading and trailing corner of the transition. If you do not specify a transition time, τ defaults to one unit of time as defined by the ‘default_transition compiler directive. If you specify a transition time of 0, the output is abruptly discontinuous. Avoid assigning a Z-filter with 0 transition time directly to a branch because doing so greatly slows the simulation. Finally, t0 specifies the time of the first sample/transition and is also optional. If not given, the first transition occurs at t=0.

The values of T and t0 at the first time point in the analysis are stored, and those stored values are used at all subsequent time points. The array values used to define a filter are used at all subsequent time points, so changing array values during an analysis has no effect on the filter.

The Z-transform filters are subject to the restrictions listed in “Restrictions on Using Analog Operators”.

Zero-Pole Z-Transforms

Use zi_zp to implement the zero-pole form of the Z-transform filter.

zi_zp(expr,
 
ζ, 
ρ
,
 
T [ , τ [ , 
t
0] ])

ζ (zeta) is a fixed or parameter-sized 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. ρ (rho) is a fixed or parameter-sized vector of N real pairs, one for each pole. The poles are given in the same manner as the zeros. If you use array literals to define the ζ and ρ vectors, the values must be constant or dependent upon parameters only. You cannot use array values defined by variables.

The transfer function is

where and are the real and imaginary parts of the zero, and and are the real and imaginary parts of the pole. If a root (a pole or zero) is real, you must specify the imaginary part as 0. If a root is complex, its conjugate must also be present. If a root is the origin, the term associated with it is implemented as

z , where r is the root. If a list of poles or zeros is empty, unity is used for the corresponding denominator or numerator.

Zero-Denominator Z-Transforms

Use zi_zd to implement the zero-denominator form of the Z-transform filter.

zi_zd(expr,
 
ζ, d, 
T 
[
 
,
 τ 
[
 
, t0] ])

ζ (zeta) is a fixed or parameter-sized 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. d is a fixed or parameter-sized vector of N real numbers that contains the coefficients of the denominator. If you use array literals to define the ζ and d vectors, the values must be constant or dependent upon parameters only. You cannot use array values defined by variables.

The transfer function is

where and are the real and imaginary parts of the zero, and is the coefficient of the power of z in the denominator. If a zero is real, you must specify the imaginary part as 0. If a zero is complex, its conjugate must also be present. If a zero is the origin, the term associated with it is implemented as

z .

Numerator-Pole Z-Transforms

Use zi_np to implement the numerator-pole form of the Z-transform filter.

zi_np(expr, n,
 
ρ, T
 
[
 
,
 τ 
[
 
,
 
t
0
] ])

n is a fixed or parameter-sized vector of M real numbers that contains the coefficients of the numerator. ρ (rho) is a fixed or parameter-sized 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. If you use array literals to define the n and ρ vectors, the values must be constant or dependent upon parameters only. You cannot use array values defined by variables.

The transfer function is

where is the coefficient of the power of z in the numerator, and and are the real and imaginary parts of the pole. If a pole is real, the imaginary part must be specified as 0. If a pole is complex, its conjugate must also be present. If a pole is the origin, the term associated with it is implemented as

z .

Numerator-Denominator Z-Transforms

Use zi_nd to implement the numerator-denominator form of the Z-transform filter.

zi_nd(expr, n, d, T [ , τ [ , 
t
0] ])

n is a fixed or parameter-sized vector of M real numbers that contains the coefficients of the numerator, and d is a fixed or parameter-sized vector of N real numbers that contains the coefficients of the denominator. If you use array literals to define the n and d vectors, the values must be constant or dependent upon parameters only. You cannot use array values defined by variables.

The transfer function is

where is the coefficient of the power of

z is the coefficient of the power of s in the denominator.

Examples

The following example illustrates an ideal sampled data integrator with the transfer function

This transfer function can be implemented as

module ideal_int (in, out) ;
electrical in, out ;
parameter real T = 0.1m ;
parameter real tt = 0.02n ;
parameter real td = 0.04m ;
analog begin
    // The filter is defined with constant array literals.
    V(out) <+ zi_nd(V(in), {1}, {1,-1}, T, tt, td) ;
end
endmodule

The next example illustrates additional ways to use parameters and arrays to define filters.

module zi (in, out);
electrical in, out;
parameter real T = 0.1;
parameter real tt = 0.02m;
parameter real td = 0.04m;
parameter real n0 = 1;
parameter integer start_num = 0;
parameter integer num_d = 2;
real nn[0:0];                            // Fixed-sized array
real dd[start_num:start_num+num_d-1]; // Parameter-sized array
real d;
analog begin
 // The arrays are initialized at the beginning of the listed analyses.
 @(initial_step("ac","dc","tran")) begin
d = 1*n0;
nn[start_num] = n0;
dd[start_num] = d; dd[1] = -d;
end
 V(out) <+ zi_nd( V(in), nn, dd, T, tt, td);
end
endmodule

Displaying Results

Verilog-AMS provides these tasks for displaying information: $strobe, $display, $monitor, $write, and $debug.

$strobe

Use the $strobe task to display information on the screen. $strobe and $display use the same arguments and are completely interchangeable. $strobe is supported in both analog and digital contexts.

strobe_task ::=
        $strobe [ ( { list_of_arguments } ) ]
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The $strobe task prints a new-line character after the final argument. A $strobe task without any arguments prints only a new-line character.

Each argument is a quoted string or an expression that returns a value.

Each quoted string is a set of ordinary characters, special characters, or conversion specifications, all enclosed in one set of quotation marks. Each conversion specification in the string must have a corresponding argument following the string. You must ensure that the type of each argument is appropriate for the corresponding conversion specification.

You can specify an argument without a corresponding conversion specification. If you do, an integer argument is displayed using the %d format, and a real argument is displayed using the %g format.

Special Characters

Use the following sequences to include the specified characters and information in a quoted string.

Use this sequence To include

\n

The new-line character

\t

The tab character

\\

The backslash character, \

\"

The quotation mark character, "

\ddd

A character specified by 1 to 3 octal digits

%%

The percent character, %

%m or %M

The hierarchical name of the current module, function, or named block

Conversion Specifications

Conversion specifications have the form

% [ flag ] [ field_width ] [ . precision ] format_character

where flag, field_width, and precision can be used only with a real argument.

flag is one of the three choices shown in the table:

flag Meaning

-

Left justify the output

+

Always print a sign

Blank space, or any character other than a sign

Print a space

field_width is an integer specifying the minimum width for the field.

precision is an integer specifying the number of digits to the right of the decimal point.

format_character is one of the following characters.

format_ character Type of Argument Output Example Output

b or B

Binary format

00000000000000000000000000111000

c or C

Integer

ASCII character format

d or D

Integer

Decimal format

191, 48, -567

e or E

Real

Real, exponential format

-1.0, 4e8,
34.349e-12

f or F

Real

Real, fixed-point format

191.04, -4.789

g or G

Real

Real, exponential, or decimal format, whichever format results in the shortest printed output

9.6001, 7.34E-8,
-23.1E6

h or H

Integer

Hexadecimal format

3e, 262, a38, fff, 3E, A38

o or O

Integer

Octal format

127, 777

r or R

Real

Engineering notation format

123,457M, 12.345K

s or S

String constant

String format

Examples of $strobe Formatting

Assume that module format_module is instantiated in a netlist file with the instantiation

formatTest format_module

The module is defined as

module format_module ; 
integer ival ;
real rval ;
analog begin 
    ival = 98 ;
    rval = 123.456789 ;
    $strobe("Format c gives %c" , ival) ;
    $strobe("Format C gives %C" , ival) ;
    $strobe("Format d gives %d" , ival) ;
    $strobe("Format D gives %D" , ival) ;
    $strobe("Format e (real) gives %e" , rval) ;
    $strobe("Format E (real) gives %E" , rval) ;
    $strobe("Format f (real) gives %f" , rval) ;
    $strobe("Format F (real) gives %F" , rval) ;
    $strobe("Format g (real)gives %g" , rval) ;
    $strobe("Format G (real)gives %G" , rval) ;
    $strobe("Format h gives %h" , ival) ;
    $strobe("Format H gives %H" , ival) ;
    $strobe("Format m gives %m") ;
    $strobe("Format M gives %M") ;
    $strobe("Format o gives %o" , ival) ;
    $strobe("Format O gives %O" , ival) ;
    $strobe("Format s gives %s" , "s string") ;
    $strobe("Format S gives %S" , "S string") ;
    $strobe("newline,\ntab,\tback-slash, \\") ; 
    $strobe("doublequote,\"") ;
end
endmodule

When you run format_module, it displays

Format c gives b
Format C gives b
Format d gives 98
Format D gives 98
Format e gives 1.234568e+02
Format E gives 1.234568e+02
Format f gives 123.456789
Format F gives 123.456789
Format g gives 123.457
Format G gives 123.457
Format h gives 62
Format H gives 62
Format m gives formatTest
Format M gives formatTest
Format o gives 142
Format O gives 142
Format s gives s string
Format S gives S string
newline,
tab, back-slash, \
doublequote,"

$display

Use the $display task to display information on the screen. $display is supported in both analog and digital contexts.

display_task ::=
        $display [ ( { list_of_arguments } ) ]
list_of_arguments ::=
        argument
|   list_of_arguments , argument

$display and $strobe use the same arguments and are completely interchangeable. For guidance, see “$strobe”.

$write

Use the $write task to display information on the screen. This task is identical to the $strobe task, except that $strobe automatically adds a newline character to the end of its output, whereas $write does not. $write is supported in both analog and digital contexts.

write_task ::=
        $write [ ( { list_of_arguments } ) ]
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The arguments you can use in list_of_arguments are the same as those used for $strobe. For guidance, see “$strobe”.

$debug

Use the $debug task to display information on the screen while the analog solver is running. This task displays the values of the arguments for each iteration of the solver.

debug_task ::=
        $debug [ ( { list_of_arguments } ) ]
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The arguments you can use in list_of_arguments are the same as those used for $strobe. For guidance, see “$strobe”.

$monitor

Use the $monitor task to display information on the screen. This task is identical to the $strobe task, except that $monitor outputs only when an argument changes value.$monitor is supported in only digital contexts.

$monitor_task ::=
        $monitor [ ( { list_of_arguments } ) ]
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The arguments you can use in list_of_arguments are the same as those used for $strobe. For guidance, see “$strobe”.

Specifying Power Consumption

Use the $pwr system task to specify the power consumption of a module. The $pwr task is supported in only analog contexts.

The $pwr task is a nonstandard Cadence-specific language extension.
pwr_task ::=
        $pwr( expression )

expression is an expression that specifies the power contribution. If you specify more than one $pwr task in a behavioral description, the result of the $pwr task is the sum of the individual contributions.

To ensure a useful result, your module must contain an assignment inside the behavior specification. Your module must also compute the value of $pwr tasks at every iteration. If these conditions are not met, the result of the $pwr task is zero.

The $pwr task does not return a value and cannot be used inside other expressions. Instead, access the result by using the options and save statements in the analog simulation control file. For example, using the following statement in the analog simulation control file saves all the individual power contributions and the sum of the contributions in the module named name:

name options pwr=all

For save, use a statement like the following:

save name:pwr

In each format, name is the name of a module.

For more information about the options statement, see Chapter 7 of the Spectre Circuit Simulator User Guide. For more about the save statement, see Chapter 8 of the Spectre Circuit Simulator User Guide.

Example

// Resistor with power contribution
‘include "disciplines.vams"
module Res(pos, neg);
inout pos, neg;
electrical pos, neg;
parameter real r=5;
    analog begin
        V(pos,neg) <+ r * I(pos,neg);
        $pwr(V(pos,neg)*I(pos,neg));
    end
endmodule

Working with Files

Verilog-AMS provides several functions for working with files. $fopen prepares a file for writing. $fstrobe and $fdisplay write to a file. $fclose closes an open file.

Opening a File

Use the $fopen function to open a specified file.

fopen_function ::=
        multi_channel_descriptor = $fopen ( "file_name" [ "io_mode"] ) ; |   fd = $fopen ( "file_name", type ) ;
type ::=
        "r"
|   "w"
|   "a"

multi_channel_descriptor is a 32-bit unsigned integer that is uniquely associated with file_name. The $fopen function returns a multi_channel_descriptor value of zero if the file cannot be opened.

Think of multi_channel_descriptor as a set of 32 flags, where each flag represents a single output channel. The least significant bit always refers to the standard output. The first time it is called, $fopen opens channel 1 and returns a descriptor value of 2 (binary 10). The second time it is called, $fopen opens channel 2 and returns a descriptor value of 4 (binary 100). Subsequent calls cause $fopen to open channels 3, 4, 5, and so on, and to return values of 8, 16, 32, and so on, up to a maximum of 32 open channels.

io_mode is one of three possible values: w, a, or r. The w or write mode deletes the contents of any existing files before writing to them. The a or append mode appends the next output to the existing contents of the specified file. In both cases, if the specified file does not exist, $fopen creates that file. The r mode opens a file for reading. An error is reported if the file does not exist.

The $fopen function reuses channels associated with any files that are closed.

file_name is a string that can include the special commands described in “Special $fopen Formatting Commands”. If file_name contains a path indicating that the file is to be opened in a different directory, the directory must already exist when the $fopen function runs. file_name (together with the surrounding quotation marks) can also be replaced by a string parameter.

type (allowed in initial or always blocks, but not in analog blocks) is a character string or a reg that indicates how the file is to be opened. The value "r" opens the file for reading, "w" truncates the file to zero length or creates the file for writing, "a" opens the file for appending, or creates the file for writing.

For example, to open a file named myfile, you can use the code

integer myChanDesc ;
myChanDesc = $fopen ( "myfile" ) ;

Special $fopen Formatting Commands

The following special output formatting commands are available for use with the $fopen function.

Command Output Example

%C

Design filename

input.scs

%D

Date (yy-mm-dd)

94-02-28

%H

Host name

hal

%S

Simulator type

spectre

%P

Unix process ID #

3641

%T

Time (24hh:mm:ss)

15:19:25

%I

Instance name

opamp3

%A

Analysis name

dc0p, timeDomain, acSup

The special output formatting commands can be followed by one or more modifiers, which extract information from UNIX filenames. (To avoid opening a file that is already open, the %C command must be followed by a modifier.) The modifiers are:

Modifier Extracted information

:r

Root (base name) of the path for the file

:e

Extension of the path for the file

:h

Head of the path for any portion of the file before the last /

:t

Tail of the path for any portion of the file after the last /

::

The (:) character itself

Any other character after a colon (:) signals the end of modifications. That character is copied with the previous colon.

The modifiers are typically used with the %C command although they can be used with any of the commands. However, when the output of a formatting command does not contain a / and “.”, the modifiers :t and :r return the whole name and the :e and :h modifiers return “.”. As a result, be aware that using modifiers with formatting commands other than %C might not produce the results you expect. For example, using the command

$fopen("%I:h.freq_dat") ;

opens a file named ..freq_dat.

You can use a concatenated sequence of modifiers. For example, if your design file name is res.ckt, and you use the statement

$fopen("%C:r.freq_dat") ;

then

As a result, the name of the opened file is res.freq_dat.

The following table shows the various filenames generated from a design filename (%C) of

/users/maxwell/circuits/opamp.ckt 

by using different formatting commands and modifiers.

Command and Modifiers Resulting Opened File

$fopen("%C");

None, because the design file cannot be overwritten.

$fopen("%C:r");

/users/maxwell/circuits/opamp

$fopen("%C:e");

ckt

$fopen("%C:h");

/users/maxwell/circuits

$fopen("%C:t");

opamp.ckt

$fopen("%C::");

/users/maxwell/circuits/opamp.ckt:

$fopen("%C:h:h");

/users/maxwell

$fopen("%C:t:r");

opamp

$fopen("%C:r:t");

opamp

$fopen("/tmp/%C:t:r.raw");

/tmp/opamp.raw

$fopen("%C:e%C:r:t");

ckt.opamp

$fopen("%C:r.%I.dat" );

/users/maxwell/circuits/
opamp.opamp3.dat

When $fopen is used on a compressed file, the file is copied to the /tmp directory and uncompressed there.

Reading from a File

Use the $fscanf and $fgets functions to read information from a file.

$fscanf

Use the $fscanf function to read information from a file.

fscanf_function ::=
        $fscanf (multi_channel_descriptor , "format" { , storage_arg } )

The multi_channel_descriptor that you specify must have a value that is associated with one or more currently open files. The format describes the matching operation done between the $fscanf storage arguments and the input from the data file. The $fscanf function sequentially attempts to match each formatting command in this string to the input coming from the file. After the formatting command is matched to the characters from the input stream, the next formatting command is applied to the next input coming from the file. If a formatting command is not a skipping command, the data read from the file to match a formatting command is stored in the formatting command’s corresponding storage_arg. The first storage_arg corresponds to the first nonskipping formatting command; the second storage_arg corresponds to the second nonskipping formatting command. This matching process is repeated between all formatting commands and input data. The formatting commands that you can use are the same as those used for $strobe. See “$strobe” for guidance.

For example, the following statement reads data from the file designated by fptr1 and places the information in variables called db1 and int.

$fscanf(fptr1, "Double = %e and Integer = %d", dbl, int);

$fgets

Use the $fgets function to read the characters from a file, until a newline character or End of File (EOF) condition is encountered, and store the information in a string variable.

fgets_function ::=
        $fgets ( "str" { , [ multi_channel_descriptor ] } )

The multi_channel_descriptor that you specify must have a value that is associated with the currently open file. If an error occurs while reading the file, the function returns zero, otherwise, it returns the number of characters it reads from the file.

Writing to a File

Verilog-AMS provides three input/output functions for writing to a file: $fstrobe, $fdisplay, $fwrite, $fmonitor, $fdebug. The $fstrobe and $fdisplay functions use the same arguments and are completely interchangeable. The $fwrite function is similar but does not insert automatic carriage returns in the output.

$fstrobe

Use the $fstrobe function to write information to a file.

fstrobe_function ::=
        $fstrobe (multi_channel_descriptor {,list_of_arguments })
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The multi_channel_descriptor that you specify must have a value that is associated with one or more currently open files. The arguments that you can use in list_of_arguments are the same as those used for $strobe. See “$strobe” for guidance.

For example, the following code fragment illustrates how you might write simultaneously to two open files.

integer mcd1 ;
integer mcd2 ;
integer mcd ;
@(initial_step) begin
    mcd1 = $fopen("file1.dat") ;
    mcd2 = $fopen("file2.dat") ;
end
.
.
.
mcd = mcd1 | mcd2 ; // Bitwise OR combines two channels
$fstrobe(mcd, "This is written to both files") ;

$fdisplay

Use the $fdisplay function to write information to a file.

fdisplay_function ::=
        $fdisplay (multi_channel_descriptor {,list_of_arguments })
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The multi_channel_descriptor that you specify must have a value that is associated with a currently open file. The arguments that you can use in list_of_arguments are the same as those used for $strobe. See “$strobe” for guidance.

$fwrite

Use the $fwrite function to write information to a file.

fwrite_function ::=
        $fwrite (multi_channel_descriptor {,list_of_arguments })
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The multi_channel_descriptor that you specify must have a value that is associated with a currently open file. The arguments that you can use in list_of_arguments are the same as those used for $strobe. See “$strobe” for guidance.

The $fwrite function does not insert automatic carriage returns in the output.

$fmonitor

The $fmonitor function is similar to $monitor. However, it prints the values of variables or expressions that are specified as an argument to the task to a specified file.

fmonitor_function ::=
        $fmonitor ( multi_channel_descriptor {,list_of_arguments })
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The multi_channel_descriptor that you specify must have a value that is associated with a currently open file.

$fdebug

The $fdebug function is similar to $debug. However, it prints the information to a file.

fdebug_function ::=
        $fdebug ( multi_channel_descriptor {,list_of_arguments })
list_of_arguments ::=
        argument
|   list_of_arguments , argument

The multi_channel_descriptor that you specify must have a value that is associated with the currently open file.

$ferror

ferror_function ::=      $ferror (multi_channel_descriptor ,argument )

Use the $ferror function to write the error information generated by the current input/output function to a string variable.

The function also returns an integral value of the error code. If no error is generated by the input/output function, the $ferror function returns zero and the string variable does not contain anything.

Finding the File Position

$ftell

Use the $ftell function to return the offset value from the beginning of a file.

ftell_function ::= 
        $ftell ( multi_channel_descriptor ) ;

The offset value can be used by the $fseek function to reposition the file.

The multi_channel_descriptor that you specify must have a value that is associated with the currently opened file.

$fseek

Use the $fseek function to set the position of the next input or output operation on a file.

fseek_function ::=      $fseek ( multi_channel_descriptor, offset_value, opearation_value) ;

The new postion depends on the value specified for operation_value and can be any of the following:

0 – sets the position equal to offset_value

1 – sets the position to the current location after adding offset_value

2 – sets the position to End of File (EOF) after adding offset_value

The $fseek function can be used to position the file pointer to any position in the file, however, when data is written to the file, the file pointer is ignored and the output is written at the end of the file and the file pointer is automatically positioned at the end of the output.

If an error occurs while repositioning the file, the function returns -1, otherwise, it returns 0.

$rewind

Use the $rewind function to set the position of the next input or output operation on a file.

rewind_function ::=      $rewind ( multi_channel_descriptor) ;

$rewind is equivalent to $fseek (multi_channel_descriptor, 0, 0)

Closing a File

Use the $fclose function to close a specified file.

file_close_function ::= 
        $fclose ( multi_channel_descriptor ) ;

The multi_channel_descriptor that you specify must have a value that is associated with the currently open file that you want to close.

Simulator Control Functions

Verilog-AMS provides the following simulator control functions:

For simulation tools, the $fatal, $error, $warning, and $info functions also report the simulation run time at which the function is called. You can also use these functions to include additional information using the same format as the $display function.

$finish

If the $finish function is called during an accepted iteration, the simulator exits after the current solution is complete and returns the control to the operating system. $finish called during a rejected iteration has no effect.

finish_function ::=
        $finish [( msg_level )] ;
msg_level ::=
        0 | 1 | 2

The msg_level value determines which diagnostic messages print before control returns to the operating system. The default msg_level value is 1.

msg_level Messages printed

0

None

1

Simulation time and location

2

Simulation time, location, and statistics about the memory and CPU time used in the simulation

In this release, the $finish function always behaves as though the msg_level value is 0, regardless of the value you actually use.

If the $finish function is called from an analog initial block, the simulator does not perform any simulation and exits with a message. In addition, when a simulation exits due to $finish, all appropriate final_step blocks are triggered.

For example, to make the simulator exit, you might code

$finish ;

$finish_current_analysis

Use the $finish_current_analysis function to stop the current transient analysis without exiting the simulator. The $finish_current_analysis enables you to stop the ongoing transient analysis and continue to run the remaining analysis. The syntax of $finish_current_analysis is the following:

finish_function ::=
$finish_current_analysis [( msg_level )] ;
msg_level ::=
        0 | 1 | 2

where msg_level value works exactly the same way as it does in the $finish function.

The $finish_current_analysis can be used to stop only the transient analysis and not any other analysis type.

$stop

The $stop function is treated the same as the $finish function.

stop_function ::=
        $stop [( msg_level )] ;
msg_level ::=
        0 | 1 | 2
In this release, the $stop function always behaves as though the msg_level value is 0, regardless of the value you actually use. In addition, the $stop function cannot be used within an analog initial block.

$fatal

Use the $fatal function to generate a runtime fatal error message and make the simulator exit with an error code. The first argument to the $fatal function is the same as the $finish function and identifies which diagnostic message should the simulator print before exiting.

fatal_function ::=
        $fatal [ ( msg_level [ , message_argument { , message_argument } ] ) ] ;

msg_level ::=      0 | 1 | 2

msg_level Messages printed

0

None

1

Simulation time and location

2

Simulation time, location, and statistics about the memory and CPU time used in the simulation

If you call the $fatal function from an analog initial block, the initialization is aborted after the message is generated and the simulation exits.

Currently, the $fatal function, like the $finish function, behaves as though msg_level is 0 regardless of the value that you specify for msg_level.

$error

Use the $error function to generate a runtime error message.

error_function ::=
     $error [ ( [ message_argument { , message_argument } ] ) ] ;

If you call the $error function from an analog initial block, the initialization continues after the message is generated.

$warning

Use the $warning function to generate a runtime warning message, which can be suppressed by the simulator.

warning_function ::=
     $warning [ ( [ message_argument { , message_argument } ] ) ] ;

If you call the $warning function from an analog initial block, the initialization and simulation is not affected.

$info

Use the $info function to generate an informational message that does not include any severity.

info_function ::=
     $info [ ( [ message_argument { , message_argument } ] ) ] ;

If you call the $info function from an analog initial block, the initialization and simulation is not affected.

The $fatal, $error, $warning, and $info functions also report the simulation run time at which the severity system task is called. In addition, you can use these functions to include additional information using the same format as the $display function.

Non-fatal system severity functions ($error, $warning, and $info) called during a rejected iteration do not have any effect. $fatal ends the simulation without checking whether the iteration should be rejected.

Changing the Global Circuit Temperature

Use the $cds_set_temperature system function to change the global circuit temperature parameter during simulation.

set_temperature_function ::=
    $cds_set_temperature(expression)

expression should be a real-type expression that represents the temperature to be set in degree Celsius. You can use variables and parameters in the expression.

When $cds_set_temperature() is called during simulation, the simulation behavior changes in a way similar to dynamic parameter simulation. For example:

module alter_temp( a, b);
electrical a, b;
real temper = 0;
    analog begin
        @(timer(200n)) begin
            temper = 30.0;
            $cds_set_temperature( temper );
        end
        @(timer(400n)) begin
            temper = 32.0;
            $cds_set_temperature( temper );
        end
    end
endmodule

Following example of using $cds_set_temperature in SystemVerilog.

module task1();
  var real r1, r2;
  task T(input r1, output r2);
    r2 = r1;
    $display("TASK T from task1: r1: %f r2: %f", r1,r2);
#10
    $cds_set_temperature(10);
    $display("Changing temperature into 10 from task T");
  endtask
  initial begin
    T(r1, r2);
  end
endmodule
module sv_child(r3,r4);
 input var real r3;
 output var real r4;
  function func(input r4);
  $display("FUNC: %f", r4);
  $cds_set_temperature(20);
  $display("Changing temperature into 20 from func");
  endfunction
  real tempVal;
  task T(input r3, output r2);
    r2 = r3;
#5    $cds_set_temperature(30);
    $display("Changing temperature into 30 from task T");
    $display("TASK from top: r3:%f r2:%f", r3,r2);
  endtask
  var real r1, r2;
  task1 task1();
  initial begin
    r1 = 1.1;
    #10;
    task1.T(r1, r2);
    #15;
    T(r1, r2);
#5    $cds_set_temperature(40);
    $display("Changing temperature into 40 from initial begin");
#5    $cds_set_temperature(41.5);
    $display("Changing temperature into 41.5 from initial begin");
#20 tempVal=60;
#20 tempVal=80;
#30 tempVal=100;
  end
  always @(tempVal) begin
    $cds_set_temperature(tempVal);
    $display("Changing temperature into %f from initial begin", tempVal);
  end
endmodule

Entering Interactive Tcl Mode

Use the $stop function to make the simulator enter interactive mode and display a Tcl prompt.

stop_function ::=
        $stop [( msg_level )] ;
msg_level ::=
        0 | 1 | 2

The msg_level value determines which diagnostic messages print before the simulator starts the interactive mode. The default msg_level value is 1.

msg_level Messages printed

0

None

1

Simulation time and location

2

Simulation time, location, and statistics about the memory and CPU time used in the simulation

For example, to make the simulator go interactive, you might code

$stop ;

User-Defined Functions

Verilog-AMS supports user-defined functions. By defining and using your own functions, you can simplify your code and enhance readability and reuse. Each function can be a digital function (as defined in IEEE 1364-1995 Verilog HDL) or an analog function.

Declaring an Analog User-Defined Function

To define an analog function, use this syntax:

analog_function_declaration ::=
        analog function [ type ] function_identifier ;
        function_item_declaration {function_item_declaration}
        statement
        endfunction
type ::=
        integer
|   real
function_item_declaration ::=
        input_declaration
    |   block_item_declaration
block_item_declaration ::=
        integer_declaration
    |   real_declaration

type is the type of the value returned by the function. The default value is real.

statement cannot include analog operators and cannot define module behavior. Specifically, statement cannot include

statement can include references to

You can declare local variables to be used in the function.

Each function you define must have at least one declared input. Each function must also assign a value to the implicitly defined internal variable with the same name as the function.

For example,

analog function real chopper ;
    input sw, in ; // The function has two declared inputs.
    real sw, in ;
//The next line assigns a value to the implicit variable, chopper.
    chopper = ((sw > 0) ? in : -in) ;
endfunction

The chopper function takes two variables, sw and in, and returns a real result. You can use the function in any subsequent function definition or in the module definition.

Calling a User-Defined Analog Function

To call a user-defined analog function, use the following syntax.

analog_function_call ::=
        function_identifier ( expression { , expression } )

function_identifier must be the name of a defined function. Each expression is evaluated by the simulator before the function runs. However, do not rely on having expressions evaluated in a certain order because the simulator is allowed to evaluate them in any order.

An analog function must not call itself, either directly or indirectly, because recursive functions are illegal. Analog function calls are allowed only inside of analog blocks.

The module phase_detector illustrates how the chopper function can be called.

module phase_detector(lo, rf, if0) ;
inout lo, rf, if0 ;
electrical lo, rf, if0 ;
parameter real gain = 1 ;
 function real chopper;
input sw, in;
real sw, in;
chopper = ((sw > 0) ? in : -in);
endfunction
analog
    V(if0) <+ gain * chopper(V(lo),V(rf));  //Call from within the analog block.
endmodule

Return to top
 ⠀
X