Verilog-A Basic Structure and Syntax
Introduction¶
A Verilog-A module is similar in concept to a SPICE subcircuit or a Verilog module, but with a focus on continuous-time analog behavior. Everything from terminal definitions to parameterization and analog equations lives inside the module structure.
The module structure serves four major roles:
- Encapsulating behavior into a reusable block
- Defining terminals and disciplines that determine how the model interacts with circuit node
- Allowing parameterization to adapt the model for different configurations. In some simulators (e.g., Cadence virtuoso), the parameters appear as symbol properties at higher hierarchy.
- Providing a place for analog equations, which form the core of the model
Module Declaration¶
Every Verilog-A model begins with a module keyword and ends with endmodule. The module declaration optionally lists terminals:
module resistor(p, n);
inout p, n;
electrical p, n;
Key points¶
- Module name: Should be descriptive, e.g.,
resistor,opamp_simple, orvco_behavioral. - Terminal list: Defines the connection points. They work like SPICE pins.
- Verilog-A uses
inoutfor all analog terminals (because analog nodes inherently allow bidirectional flow).
This simple structure sets the stage for adding behavior.
Terminals and Disciplines¶
Terminals, also known as ports or nodes, represent the connection points of a module to the external circuit or to other internal components. They are the interface through which signals and quantities (like voltage and current in electrical circuits) interact.
Terminals are declared within a module definition, typically with a direction (input, output, or inout) and a discipline.
module resistor(p, n);
inout p, n; // terminals
electrical p, n; // discipline
// ...
endmodule
A discipline defines the nature of the physical quantities associated with a terminal or a branch. It specifies the domain (continuous or discrete) and the potential and flow natures (e.g., voltage and current for electrical, force and velocity for mechanical). It ensure type-checking and compatibility between different parts of an analog model. They enforce rules for how different physical quantities can interact.
Terminals must be declared with a discipline, which describes what physical quantities the terminal carries. The most common discipline in Verilog-A is:
electrical
The electrical discipline, commonly used in Verilog-A, defines voltage as the potential nature and current as the flow nature. When a terminal is declared as electrical, it implies that voltage and current are the relevant quantities at that point.
Example¶
inout p, n;
electrical p, n;
If you forget to declare the discipline, simulators cannot interpret the node's physical meaning.
Common disciplines¶
Other disciplines are :
| Name | Potential | Flow | Domain |
|---|---|---|---|
| electrical | Voltage | Current | Continous |
| thermal | Temperature | Power | Continous |
| kinematic | Position | Force | Continuous |
| logic | - | - | Discrete |
But for most analog electronic applications, electrical is sufficient. The standard disciplines are included by using the line `include "disciplines.vams" at the beginning of a Verilog-A file.
Example
`include "constants.vams"
`include "disciplines.vams" //including standard discipline file
module low_pass_filter(in, out);
input in;
output out;
electrical in, out;
parameter real R = 1k;
parameter real C = 1n;
analog begin
V(out) <+ laplace_nd(V(in), {1}, {R*C, 1});
end
endmodule
Parameter Definitions¶
Parameters allow a module to be flexible, configurable, and reusable. They behave like SPICE model parameters.
Example:
parameter real R = 1k from (0:inf);
Key features¶
- Type: Most parameters are
real, butintegerandstringtypes are allowed. - Default value: Ensures the model works out-of-the-box.
- Constraints: The
from (min:max)syntax helps simulators avoid invalid values.
Parameterization is essential for building models such as:
- Variable resistors
- Configurable filters
- Op-amp gain/bandwidth models
- Device models with multiple physical parameters
Local Variables¶
Local variables are internal to the module and cannot be modified by the circuit netlist.
Example:
real v_diff;
These variables store temporary values, intermediate computations, or internal states.
The Analog Block¶
The heart of every Verilog-A module is the analog begin ... end block. This is where continuous-time equations and contribution statements are written.
Example
analog begin
I(p, n) <+ V(p, n) / R;
end
This single line implements Ohm's law:
$$ I = \cfrac{V}{R} $$
The analog block supports:
- algebraic equations
- differential equations
- Laplace-based transfer functions
- nonlinear functions (
exp,tanh,limexp) - time-based functions (
ddt,idt,timer,transition)
All analog behavior flows from the analog block.
Contribution Statements¶
Contribution statements implement KCL (Kirchhoff's Current Law) and KVL (Kirchhoff's Voltage Law):
- Current contribution:
I(a, b) <+ expression; - Voltage contribution:
V(a, b) <+ expression;
These statements do not assign values (like in programming languages). Instead, they "contribute" currents or voltages to the circuit matrix.
Capacitor¶
I(p, n) <+ C * ddt(V(p, n));
Inductor¶
V(p, n) <+ L * ddt(I(p, n));
Because contribution statements build up the circuit equation system, multiple contributions merge automatically without conflicts.
Initial Conditions and Analog Events¶
Verilog-A provides mechanisms for initializing variables and detecting events:
Initial conditions¶
analog begin
@(initial_step) v_state = 0;
Cross-event detection¶
The cross() function is a monitored event function used to detect when an analog signal or expression crosses a specific threshold (typically zero) in a specified direction. It is particularly useful for modeling analog-to-digital interfaces or other events dependent on voltage or current thresholds.
Basic Syntax
cross(expression, direction, time_tol, expr_tol, enable)
- expression (required): The analog expression or signal that is being monitored for a zero-crossing. The event is triggered when this expression crosses zero.
- direction (optional): Specifies the direction of the crossing.
- +1: Triggers only on a rising edge (when expression crosses zero from negative to positive).
- -1: Triggers only on a falling edge (when expression crosses zero from positive to negative).
- 0 (default): Triggers on either rising or falling edges.
- time_tol (optional): A time tolerance for detecting the zero-crossing. The simulator attempts to cut or extend the time step to accurately resolve the crossing within this tolerance.
- expr_tol (optional): An expression tolerance for detecting the zero-crossing. The event is triggered when the expression is within this tolerance of zero.
- enable (optional): An enable signal that, when false, prevents the cross() event from being detected.
For example :
@(cross(V(in) - vth, +1)) state = 1;
Useful for comparators, switched-capacitor systems, and oscillators.
Complete Example: Nonlinear Diode Model¶
Below is a simple diode model illustrating a complete module structure:
`include "constants.vams"
`include "disciplines.vams"
module diode(p, n);
inout p, n;
electrical p, n;
parameter real Is = 1e-14 from (0:inf);
parameter real N = 1.0 from (0:10);
real Vd;
analog begin
Vd = V(p, n);
I(p, n) <+ Is * (exp(Vd/(N*$vt)) - 1);
end
endmodule
This simple model:
- declares terminals
- defines parameters with limits
- uses local variables
- applies a physical equation
It demonstrates the complete, minimal Verilog-A structure.
Tips for Writing Good Verilog-A Modules¶
- Use parameter constraints Helps simulators avoid invalid conditions.
- Avoid discontinuities Use
transition()ortanh()for soft switching. - Group related equations together Improves readability.
- Use meaningful variable names Avoid cryptic abbreviations.
- Test models in isolation Always simulate individual modules before using them in a large system.