OpenVAF follows the Verilog-AMS Language Reference Manual 2.4.0 language standard. The current goal is to support only the analog (Verilog-A) subset defined within this standard, digital models can not (yet) be parsed.

Furthermore, the OpenVAF compiler is primarily aimed at compact modeling. For better facilitating compact modeling (and for reducing the scope of the implementation) the behavior of the compiler sometimes differs from the standard. In this document all differences between the language subset implemented by OpenVAF and the Verilog-A subset of the Verilog-AMS Language Reference Manual are documented.

#Incomplete Features

Notice: This section is currently under construction...

Some features in the Verilog-AMS Language Reference Manual are aimed at behavioral modeling or describing entire circuits. These features are hard or even impossible support when statically compiling compact models. Therefore OpenVAF purposefully does not implement these features. Here all language features not implemented by OpenVAF are laid out.

#(Analog) Event Control Statements
  • Standard Section 5.10 Analog event control statements
  • Status Syntax for events other than inital_step and final_step can't be parsed

The Verilog-AMS standard allows to mark statements with event control. Such statements are only executed when the indicated event has occurred. The events are usually not used in compact models as they may introduce discontinuities. Therefore OpenVAF only supports the inital_step and final_step events for initialization code.


There are four kinds of events specified in the standard. They are listed here with an example and an indication to show whether OpenVAF currently supports this syntax:

  • Global events (@(initial_step), @(final_step)) supported
  • Named (manually triggered) events (@foo) not supported
  • Monitored events (@(cross(V(smpl) - thresh, dir))) not supported
  • Or events (a combination of multiple other events) @(initial_step or cross(V(smpl)-2.5,+1)) not supported
#Arithmetic Bit Shift
  • Standard Section 4.2.11 Shift Operators
  • Status Arithmetic Shift Operator can not be parsed (no change planned)

Arithmetic bit shifts are not allowed in analog blocks, yet they are a sub-set of the Verilog-AMS standard that is not excluded for Verilog-A. To avoid having to maintain unused code, the arithmetic bit shift operator is not supported by the compiler.

#Additional Features

Some features that are not part of the Verilog-A standard have been added to OpenVAF. The need for these features arose when OpenVAF was used in practice for compact model compilation and parameter, extraction. Below is a table that lists these additional features and a corresponding example.

Feature Example
Voltage Derivatives ddx(foo,V(a,b))
Temperature Derivatives ddx(foo,$temperature)

In the following section each feature -including a motivation- is explained in detail. To make it easy to remain standard-compliant, OpenVAF will emit a warning by default when any one of the listed features is used.

#Symbolic Derivatives with respect to Temperature

The Verilog-AMS Language Reference Manual allows calculating derivatives with the ddx analog filter. However, only derivatives w.r.t. node voltages V(node) or branch currents (I(branch)) are allowed. For parameter extraction derivatives by ambient Temperature ($temperature) may be of interest for extracting temperature dependencies.


The behavior of the ddx analog filter is extended so that ddx(foo,$temperature) is valid. When such a derivative is evaluated, all voltages and currents are assumed to be independent of temperature. Apart from this the ddx filter behaves identical as when used with nodes/branches, the derivative of the temperature is calculated by repeated application of the chain rule.

x = ddx($temperature,$temperature)
y = ddx(v(node),$temperature)
z = ddx(i(branch),$temperature)
// x = 1, y=z=0

foo = 20*exp($temperature/10)+V(node)
bar = ddx(foo,$temperature)
// bar = 2*exp($temperature/10)
#Symbolic Derivatives with respect to Voltages

Equations of compact models usually depend upon voltage differences V(a,b) (or equivalently branch voltage V(br_ab)). The derivatives of these model Equations are required/useful during parameter extraction and for use in circuit simulators. However, Verilog-A only allows derivatives w.r.t. to node potentials.

Usually, such voltage derivatives are instead calculated with respect to the derivative of the voltage's upper node ddx(foo,V(a,b) = ddx(foo,V(a)). This approach can fail when an equation depends on multiple branch voltages, as is demonstrated by the example below. For ensuring correct behavior it is therefore more desirable to calculate the derivative by V(a,b) directly.

foo = V(a,b) + V(c,a)
dfoo1 = ddx(foo, V(a))
dfoo2 = ddx(foo,V(a,b))
// dfoo1 = 0, dfoo2 = 1

The behavior of the ddx analog filter is extended so that ddx(foo,V(node1,node2)) is valid. Branch currents are treated as constants. Voltage derivatives w.r.t. V(node1,node2) are implemented as follows:

  • The derivative of V(node1,node2) is 1
  • The derivative of V(node2,node1) is -1
  • The derivative of V(branchX) is 1 if the branches nodes are node1 and node2: branch (node1, node2) branchX
  • The derivative of V(branchX) is -1 if the branches nodes are node2 and node1: branch (node2, node1) branchX
  • In all other cases the derivative is 0

Otherwise, the ddx filter behaves identical as when used with nodes/branches. The derivative of the argument is calculated by repeated application of the chain rule.


branch (b,e) br_be;

    Vt = $vt;
    Ib = Isbc*exp(V(b,c)/Vt) + Isbe*exp(V(br_be)/Vt);
    gbc = ddx(Ib, V(b,c)); // gbc =  Isbc/Vt*exp(V(b,c)/Vt)
    gbe = ddx(Ib, V(b,e)); // gbe =  Isbe/Vt*exp(V(b,c)/Vt)


#Technical Background

For performance reasons ODIC uses voltage derivatives instead of potential derivatives to calculate the Jacobian matrix entries. Consider a network with two nodes a and b which are connected by a single branch br_ab whose current only depends upon the voltage difference of the two nodes. The matrix entries can then be calculated as follows:

ddx(I(<a>),V(a))=ddx(I(<b>),V(b)) = ddx(I(br_ab),V(a,b))
ddx(I(<a>),V(b))= ddx(I(<a>),V(b)) = - ddx(I(br_ab),V(a,b))

Almost all equations in compact models have above form using this technique effectively enables to reduce the number of derivatives by a factor of 4. Considering how complicated and therefore computationally expensive such derivatives can be, it is unlikely even modern compilers could optimize these duplication's away completely, and even if, it would reduce compile time significantly. Therefore it is preferable for OSDIC to calculate derivatives by voltage difference and then calculate the Matrix entries from the results.

About this wiki

commit 03285546c2db01b4d3fdde57f9e2ab790ba28c15
Author: DSPOM <dspom@protonmail.com>
Date:   2022-07-05T10:43:13+02:00

Update repo links
Clone this wiki
https://git.sr.ht/~dspom/openvaf_doc (read-only)
git@git.sr.ht:~dspom/openvaf_doc (read/write)