# Preview

This page is not yet fully complete and is missing some content.

This page is not yet fully complete and is missing some content.

OpenVAF implements the Verilog-AMS Language Reference Manual 2.4.0 language standard. The main goal is to support the analog (Verilog-A) subset defined within this standard, digital models can not (yet) be parsed. Strict adherence to the language standard was taken very seriously during development to ensure that all standard compliant models are supported.

Not all features of the Verilog-A standard are implemented yet, see our roadmap for more details. However, the subset of the standard that is used by compact models (and more) is already implemented. Therefore, OpenVAF has been released as this already suffices for all standard compact models.

To better facilitating compact modeling a few additional features were added to OpenVAF. This page documents all **differences** between the language subset implemented by OpenVAF and the Verilog-A subset of the Verilog-AMS Language Reference Manual.

Some features in the Verilog-AMS Language Reference Manual are aimed at behavioral modeling or describing entire circuits. The following features are not yet implemented by OpenVAF.

**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. Most events are usually not used in compact models as they may introduce discontinuities. OpenVAF currently supports the `inital_step`

and `final_step`

events for initialization of code. These events are executed on every iteration and time step. Historically `inital_step`

was used in compact models to mark model initialization code. OpenVAF automatically separates initialization code and therefore `intial_step`

can be ignored.

There are four kinds of events specified in the standard. They are listed below 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*

**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.

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.

In the following section each feature -including a motivation- is explained in detail. For making it easy to remain standard-compliance, OpenVAF emits a warning by default when any one of the listed features is used.

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 w.r.t. 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)
```

Equations of compact models usually depend on voltage differences `V(a,b)`

(or equivalently branch voltages `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 fails 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;
begin
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)
end
```

For performance reasons OpenVAF 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 on the voltage difference between 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 voltage differences 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 duplications away completely. Therefore, it is preferable for OpenVAF to calculate derivatives using voltage difference and then calculate the Matrix entries from the results.