Verilog-A
Verilog-A is a specialized analog hardware description language (HDL) that forms the continuous-time modeling subset of the Verilog-AMS standard, enabling behavioral descriptions of analog circuits and systems through constructs like analog procedures, nets, branches, and disciplines for electrical and non-electrical domains.[1] Developed initially by the Open Verilog International (OVI) consortium in the 1990s as an extension to the digital Verilog HDL (IEEE Std 1364), Verilog-A was standardized to address the need for a portable, high-level language for analog simulation, distinct from SPICE-like netlists by supporting both conservative (Kirchhoff-based) and signal-flow modeling paradigms.[2] It integrates seamlessly into Verilog-AMS, ratified by Accellera in 2000, and evolved through subsequent versions including 2.3.1 (2009), 2.4 (2014), and 2023 (2024), with the latest providing enhancements to analog constructs, clarifications for existing features, and improved compatibility with SystemVerilog for full-system simulation.[1][3] These versions support features such as parameter arrays, mathematical functions, noise sources, and waveform filters for accurate representation of device physics in integrated circuit design.
As the de facto standard for compact device modeling in the semiconductor industry, Verilog-A facilitates simulation across tools from vendors like Cadence, Synopsys, and Mentor Graphics, promoting model portability and reuse in mixed-signal verification workflows.[4] Its syntax emphasizes modularity with modules, terminals, and natures (defining potential and flow quantities like voltage and current), while avoiding digital event-driven semantics to focus on differential algebraic equations solved by analog solvers.[1] Key applications include transistor-level modeling for RF, power, and MEMS systems, where it supports hierarchical designs, parameter sweeps, and probabilistic behaviors without requiring low-level circuit schematics.[2] The language's evolution under Accellera reflects ongoing enhancements for emerging technologies, such as enhanced table-based modeling and interface compatibility with SystemVerilog for full-system simulation.[1]
Overview
Definition and Purpose
Verilog-A is a behavioral hardware description language (HDL) designed specifically for modeling continuous-time analog and mixed-signal systems. It serves as the analog-only subset of Verilog-AMS, focusing on the description of analog circuit behavior without incorporating digital extensions. Developed as an extension of the original Verilog HDL, Verilog-A enables the creation of high-level models that capture the mathematical and physical behaviors of analog components through declarative equations and processes.[5][2][6]
The primary purpose of Verilog-A is to facilitate high-level behavioral descriptions of analog components, supporting top-down design methodologies where complex systems can be abstracted from detailed transistor-level implementations. It supports compatibility with SPICE-based simulators by contributing to modified nodal analysis formulations through its behavioral descriptions, allowing seamless integration with traditional analog simulators while adhering to conservative semantics based on Kirchhoff's laws for electrical conservation and signal-flow semantics for non-conservative systems. This enables multi-discipline simulations across domains such as electrical, mechanical, and thermal, by defining disciplines and contributions that ensure physical consistency in modeling.[5][6][7]
In practice, Verilog-A is applied to define transistor-level models for devices like MOSFETs, as well as behavioral abstractions for higher-level components such as operational amplifiers and resistors, which can be integrated into electronic design automation (EDA) tools for efficient circuit simulation and verification. By addressing the limitations of the original Verilog HDL, which was oriented toward digital logic, Verilog-A fills a critical gap in the Verilog ecosystem for analog modeling needs in integrated circuit design.[5][6][8]
Key Characteristics
Verilog-A is designed as an analog hardware description language that emphasizes conservative and signal-flow modeling paradigms, primarily through the use of disciplines and natures to define physical domains. Disciplines group related natures, which represent potential and flow quantities in conservative systems, such as the electrical discipline pairing the Voltage nature (potential) with the Current nature (flow).[1] Natures specify attributes like absolute tolerance (abstol), access functions, and units, enabling precise representation of physical quantities across simulations.[1] This structure supports the declaration of nets with continuous disciplines, where each net must have a potential nature and may include a flow nature to model interactions like Kirchhoff's laws.[1]
The language focuses on continuous-time simulation, targeting the solution of differential equations in the analog domain via interconnected nodes, branches, and terminals that form the topology of a circuit or system.[1] Analog processes in Verilog-A execute continuously, describing relationships that hold true at all times rather than at discrete events, which distinguishes it from digital hardware description languages.[9] This approach aligns with the modified nodal analysis (MNA) formulation, where contributions from model equations are stamped into the system matrix, ensuring compatibility with SPICE-based simulators and allowing seamless integration of Verilog-A models alongside legacy SPICE netlists.[1] By adhering to MNA, Verilog-A leverages Kirchhoff's current and voltage laws to define node and branch relationships without requiring explicit matrix formulations from the modeler.[1]
Verilog-A's data types are tailored for analog modeling, featuring real numbers for parameters and constants, quantities for dynamic variables that represent continuous signals, and limited string support introduced in version 2.3 for annotations or identifiers.[1] Parameters, declared as parameter real, provide compile-time constants that influence model behavior without simulation overhead, while quantities like real or electrical types handle time-varying values in analog blocks.[9] These types, combined with discipline-specific nets, ensure numerical stability and precision in solvers.[1]
A hallmark of Verilog-A is its support for multi-discipline modeling, extending beyond electrical systems to domains like mechanical, thermal, rotational, fluid dynamics, and thermodynamics through user-defined natures and disciplines.[1] For instance, a mechanical discipline might pair Displacement (potential) with Force (flow), while thermal modeling could use Temperature and Heat Flow natures, all integrated within the same simulation framework.[1] This capability allows for system-level simulations that couple multiple physical domains, such as electro-mechanical systems, by declaring compatible natures that derive from base types and ensuring cross-discipline interactions via shared nodes.[9] Custom natures must specify domains (continuous or discrete) and attributes to maintain simulation consistency, enabling broad applicability in mixed-domain analysis.[1]
History and Standards
Development History
Verilog-A emerged in the mid-1990s as an analog extension to Verilog HDL, which had been developed in the 1980s for digital hardware description and simulation.[10][5] This extension was motivated by the growing need in the transistor-modeling community for a standardized language to describe continuous-time analog behaviors, particularly amid delays in creating a unified analog-digital hardware description language.[11] The development was driven by requirements for compact device modeling in electronic design automation (EDA) workflows, enabling behavioral descriptions of analog systems beyond traditional SPICE netlists.[12]
Initial development occurred under the Open Verilog International (OVI) organization around 1995-1996, with key contributions from engineers at Cadence Design Systems and Synopsys to standardize analog models for interoperability across EDA tools.[5][12] OVI released Verilog-A version 1.0 in August 1996 as the baseline specification, proposed by OVI's Analog Technical Subcommittee earlier that year, focusing on core analog operators and constructs for electrical and non-electrical disciplines.[5] Following this, Verilog-A was integrated into the broader Verilog-AMS framework after the release of Verilog-AMS 1.3 in 1998, allowing mixed-signal simulations while maintaining Verilog-A as the pure analog subset.[11]
Version evolution continued under OVI and its successor. In 2000, version 2.0 introduced mathematical functions such as ceiling and floor operators to enhance expression capabilities for analog modeling.[11] That same year, OVI merged with VHDL International to form Accellera, which assumed responsibility for maintenance and extensions, ensuring compatibility with evolving EDA needs without disrupting established models.[13] Subsequent updates included version 2.3 in 2008, which added support for string data types to facilitate parameter passing and debugging in models, and version 2.4 in 2014, which refined analog behavioral descriptions for improved simulation accuracy and convergence.[14][11] The most recent major release is the Verilog-AMS LRM 2023 (Accellera Std VAMS-2023), released February 14, 2024, which includes enhancements to the Verilog-A subset such as improved parameter handling (e.g., paramsets), new system functions (e.g., $table_model for table-based modeling), and analog constructs like net_discipline.[1] As of November 2025, Accellera continues maintenance through its SystemVerilog-AMS Working Group to preserve backward compatibility amid evolving mixed-signal extensions.[15]
Standardization and Availability
Verilog-A was initially standardized by Open Verilog International (OVI) in 1996 as part of efforts to extend the Verilog hardware description language for analog modeling.[16] In 2000, following the merger of OVI and VHDL International, stewardship transferred to Accellera, which has since overseen its development and maintenance.[16] While Verilog-A aligns closely with the base Verilog HDL standardized as IEEE Std 1364, it lacks a dedicated IEEE standard number, remaining an Accellera-managed specification integrated into broader analog/mixed-signal frameworks.
The core definition of Verilog-A appears as a continuous-time subset within the Verilog-AMS Language Reference Manual (LRM), with explicit compliance requirements outlined in its annexes to ensure analog-only usage without digital extensions.[17] The most recent major release, the Verilog-AMS LRM 2023 (Accellera Std VAMS-2023) dated February 14, 2024, formalizes Verilog-A's syntax, semantics, and behavioral modeling constructs for analog circuit simulation as defined in Annex C.[1][18]
Specifications for Verilog-A are freely available for download from the Accellera website, including the full LRM as VAMS-LRM-2023.pdf, enabling widespread adoption without licensing barriers.[17] Open-source tools such as OpenVAF provide compliance verification by compiling Verilog-A code against the LRM subset, supporting model development and testing in academic and industrial settings.[19]
The Compact Model Coalition (CMC), under the Silicon Integration Initiative (Si2), issues guidelines for standardizing Verilog-A model code to promote interoperability across simulators, including conventions such as appending "_cmc" suffixes to model names and defining parameter aliases for consistent implementation.[20] These policies, released as recently as March 2025, emphasize required components like discipline declarations and nature definitions to ensure robust compact model distribution.[21]
As of November 2025, ongoing maintenance is handled by Accellera's SystemVerilog-AMS Working Group to preserve backward compatibility amid evolving mixed-signal extensions.[15]
Language Syntax
Basic Structure and Modules
Verilog-A models are organized into modules, which serve as the fundamental building blocks for describing analog behaviors. A module is declared using the syntax module module_name (port_list); followed by declarations and statements, and terminated by endmodule. Ports in Verilog-A are typically declared as inout, input, or output nets disciplined as electrical, such as inout electrical port_name;, allowing bidirectional, input-only, or output-only connections for analog signals.[14] This structure enables hierarchical modeling where modules can instantiate other modules, facilitating reusable components for circuit simulation.[14]
Disciplines and natures provide the foundational framework for defining signal types and their physical attributes in Verilog-A. A nature is specified with nature nature_name; attribute = value; endnature, where attributes include units (e.g., "V" for voltage), tolerances (e.g., abstol = 1uV), and access functions. Disciplines bind these natures to potentials and flows, using the syntax discipline discipline_name; potential nature_name; flow nature_name; enddiscipline, as in discipline electrical; potential Voltage; flow [Current](/page/Current); enddiscipline for standard electrical simulations.[14] These declarations must precede module usage and establish the domain (continuous for analog) for accurate behavioral modeling.[14]
Parameters in Verilog-A allow tunable model properties and are declared with parameter type parameter_name = value from [range];, supporting types like real or integer, optional ranges (e.g., [0:inf)), and units (e.g., 1k or "ohm"). For instance, parameter real resistance = 1k from [0:inf); defines a non-negative resistance value with kiloohm units.[14] Parameters can include descriptive attributes and are often overridden during instantiation to customize module behavior without altering the source code.[14]
Nets represent nodes in the circuit, declared as discipline_name [range] net_name;, such as electrical [0:3] bus; for a four-node electrical bus, while branches define potential differences or flows between nets with branch (node1, node2) branch_name;, exemplified by branch (p, n) resistor_branch;.[14] These declarations enable precise connectivity modeling, with nets supporting arrays for multi-bit signals and branches facilitating contribution statements in analog processes.[14]
Hierarchical referencing in Verilog-A allows access to signals across module instances using dotted notation, such as module_instance.signal (e.g., top.mod1.net1 for a net in a sub-module).[14] This follows scope rules similar to Verilog, enabling probes or controls from parent modules without flattening the hierarchy, which is essential for large-scale designs.[14]
Analog Operators and Constructs
Verilog-A includes a specialized set of analog operators and constructs that enable the modeling of continuous-time dynamics, signal delays, filtering, and stochastic behaviors essential for analog circuit simulation. These operators facilitate the description of differential and integral equations, as well as frequency-domain transformations, allowing designers to capture non-ideal effects like slew rates and noise without relying on discrete-time approximations. Unlike digital hardware description languages, these constructs operate on real-valued expressions and are evaluated during analog simulation steps, supporting both time-domain and transformed-domain analyses.[14]
Time-Domain Operators
Time-domain operators in Verilog-A handle derivatives and integrals, forming the foundation for modeling reactive components such as capacitors and inductors. The ddt operator computes the time derivative of an expression, which is crucial for representing rates of change in voltage or current; its syntax is ddt(expression[, abstol]), where abstol optionally specifies an absolute tolerance for numerical accuracy. For instance, in an inductor model, the voltage across the terminals can be expressed as V(p, n) <+ L * ddt(I(p, n)), illustrating how ddt applied to current yields the inductive voltage drop. Similarly, the idt operator performs time integration, with syntax idt(expression[, initial_condition[, assert[, abstol]]]), where initial_condition sets the starting value and assert enforces consistency checks. An example is V(out) <+ idt(I(in), 0), which integrates current to produce voltage in a basic integrator circuit, enabling the simulation of accumulated charge or flux. These operators ensure accurate transient analysis by integrating seamlessly with the simulator's time-stepping algorithms.[14]
Delay and Filter Functions
Delay and filter functions allow Verilog-A models to incorporate propagation delays and linear system responses, mimicking real-world signal transmission and frequency-selective behaviors. The absdelay function introduces an absolute time delay to an expression, using the syntax absdelay(expression, delay_time[, maxdelay]), where maxdelay limits the delay for computational efficiency. A practical application appears in transmission line modeling, such as V(out) <+ absdelay(V(in), 1n), which postpones the input signal by 1 nanosecond to simulate propagation effects. For more complex filtering, the laplace_nd operator implements an N-dimensional Laplace transform-based filter, with syntax laplace_nd(expression, numerator, denominator[, epsilon]), where numerator and denominator are arrays of coefficients defining the transfer function, and epsilon controls numerical stability. This is particularly useful for analog filters; for example, a simple low-pass filter might use V(out) <+ laplace_nd(V(in), {1}, {1, 1}, 1e-6), representing a transfer function of 1/(s + 1). These functions support s-domain (continuous) transformations.[14]
Mathematical Operators
Verilog-A extends standard mathematical operators to analog contexts, supporting trigonometric, relational, and logical operations on continuous signals for conditional and nonlinear behaviors. Trigonometric functions like sin, cos, and tan operate on real arguments in radians, enabling waveform generation; for example, V(out) <+ sin(2 * M_PI * f * $abstime) produces a sinusoidal output at frequency f. Relational operators (>, <, ==, !=, <=, >=) and logical operators (&&, ||, !) facilitate piecewise definitions, similar to those in C, but applied to analog quantities for threshold-based switching without discrete events. The transition filter, a key construct for slew limiting, smooths abrupt changes in piecewise constant signals using syntax transition(expression[, delay_time[, rise_time[, fall_time]]]), as in V(gate) <+ transition(V(in), 0, 1n, 1n), which ramps the signal with specified rise and fall times to avoid infinite slew rates in simulations. These operators prioritize smooth, differentiable expressions to maintain solver stability in analog contexts.[14]
Noise and Random Functions
To model variability and stochastic processes in analog circuits, Verilog-A provides built-in noise sources and random functions suitable for Monte-Carlo and statistical analyses. Verilog-A includes specific noise functions for representing physical noise phenomena. The white_noise function models white noise (e.g., thermal noise) with a constant power spectral density across frequencies, using the syntax white_noise(power_density [, name]), where power_density is in V²/Hz or A²/Hz. For example, in a resistor model, thermal noise can be contributed as I(noise) <+ white_noise(4 * $k * $temperature / resistance);. The flicker_noise function models 1/f (flicker) noise, with syntax flicker_noise(power_density, exponent [, name]), where power_density is the density at 1 Hz and exponent is typically 1; an example is I(noise) <+ flicker_noise(1e-12, 1);. Additionally, noise_table allows custom piecewise-linear noise spectra via noise_table(model [, name]), with a predefined model array of frequency-power pairs. These noise functions are active during small-signal noise analysis and contribute to the system's stochastic equations.[1]
Complementing the noise sources, random functions generate pseudorandom values for parameter variations or jitter. The $rdist_uniform system function generates uniform random variates within a specified range, with syntax $rdist_uniform(seed, minimum, maximum), such as $rdist_uniform(1, -1, 1) for noise injection bounded between -1 and 1, which can represent thermal noise in resistors. Complementing this, $random(seed) produces a 32-bit signed pseudorandom integer, scalable for custom distributions; for example, real noise = $random(42) / 2**31 yields a uniform distribution between -1 and 1, often used in jitter modeling. These functions are evaluated at each simulation time point or noise analysis frequency, supporting white noise sources and parameter variations without external scripting.[14]
A representative example is a basic inductor model: V(inductor) <+ inductance * ddt(I(inductor));, demonstrating the use of the ddt operator for reactive components. Overall, Verilog-A's analog operators emphasize flexibility for behavioral modeling while ensuring compatibility with SPICE-like simulators.[14]
Access Functions and Contributions
In Verilog-A, access functions provide a mechanism to read the potential and flow values of analog signals during simulation. The V() function retrieves the potential difference (voltage) across a net or between two nodes, such as V(net) for the potential at a single node relative to ground or V(node1, node2) for the difference between nodes.[5] Similarly, the I() function accesses the flow (current) through a branch or between nodes, as in I(branch) or I(node1, node2).[1] These functions are invoked within analog procedural blocks and are tied to the discipline of the nets, ensuring compatibility with conservative systems like electrical domains where V represents voltage and I represents current.[5] For instance, a variable can store an accessed value for use in expressions, as shown in real vin = V(in);.[1]
Contribution statements in Verilog-A define how the module influences the circuit's behavior by adding terms to the simulator's equations for nets and branches. These use the contribution operator <+, which appends an expression to the potential or flow of a specified net or branch, with the simulator summing all contributions across the model and circuit to solve the system.[5] The syntax follows V(net) <+ expression for potential contributions or I(branch) <+ expression for flow contributions, where the expression may include accessed values, parameters, or operators like ddt for derivatives.[1] A representative example is a resistor model: I(R1) <+ V(p, n) / R;, which contributes current inversely proportional to the voltage across nodes p and n.[5] For amplification, V(out) <+ gain * V(in); adds a scaled input voltage to the output potential.[1] Contributions are evaluated iteratively until convergence at each simulation time point, enforcing Kirchhoff's laws.[5]
To negate a contribution—effectively subtracting from the sum rather than adding—the ! operator precedes the <+, as in V(out) <+ ! (expression);, which inverts the direction of the contribution for the specified branch or net.[5] This is distinct from arithmetic negation using - within the expression and is particularly useful for modeling bidirectional flows or opposite polarities in conservative systems.[5]
All access functions and contribution statements must occur within analog blocks, which encapsulate continuous-time behavioral descriptions executed at every time point or event in the simulation.[1] The syntax is analog begin ... end, allowing sequential statements like conditionals and local variable declarations that are local to the block.[5] Local variables, declared as real or other types, persist across evaluations but are reinitialized per module instance.[1] Multiple analog blocks in a module are concatenated and evaluated in order, enabling modular descriptions of complex behaviors.[5]
Switch branches model components that toggle between sourcing potential (voltage) and flow (current), such as ideal switches or relays, without requiring explicit discontinuity notifications.[1] Branches are declared as branch (node1, node2) branch_name;, and switching is achieved through conditional contributions based on a control net, where the branch acts as a potential source when V(branch) <+ expression; is active or a flow source when I(branch) <+ expression; dominates.[5] For on/off behavior, an if statement on the control net determines the contribution type; for example, if the control voltage exceeds a threshold, V(pout, nout) <+ 0.0; enforces zero potential difference (closed switch), else I(pout, nout) <+ 0.0; sets zero current (open switch).[1] This approach leverages the simulator's handling of source switching, ensuring numerical stability in transient analyses.[5]
Advanced Features
Behavioral Modeling
Behavioral modeling in Verilog-A enables the description of complex analog behaviors at a higher abstraction level than primitive components, allowing designers to encapsulate custom functionalities within modules for reuse in circuit simulations. This approach supports the creation of parameterized models that capture non-linear dynamics, noise characteristics, and sensitivity analyses without relying solely on basic operators. By leveraging procedural constructs within analog blocks, behavioral models facilitate efficient simulation of integrated circuits, particularly in SPICE-like environments.[1]
User-defined analog functions form a core element of behavioral modeling, permitting the definition of reusable computational procedures that return scalar values such as real numbers or integers. These functions are declared using the analog function keyword and can accept input arguments, enabling custom implementations like signal comparators or noise generators. For instance, a function to compute the maximum voltage between two nodes might be defined as follows:
analog function real [maxValue](/page/maxValue);
inout n1, n2;
maxValue = (V(n1) > V(n2)) ? V(n1) : V(n2);
endfunction
analog function real [maxValue](/page/maxValue);
inout n1, n2;
maxValue = (V(n1) > V(n2)) ? V(n1) : V(n2);
endfunction
This function can then be invoked within an analog block, such as V(out) <+ maxValue(in1, in2);, to model limiting behaviors in amplifiers or comparators. Such functions enhance model modularity but are restricted from containing certain constructs like event controls or contribution statements to ensure deterministic evaluation during simulation. They are particularly useful for convergence aids, such as limiting functions in diode models to prevent numerical instability.[1][5]
Generate constructs in Verilog-A allow for the parametric instantiation of multiple branches or submodules, promoting scalable modeling of repetitive structures like arrays of resistors or multi-bit components. These are implemented via generate blocks with genvar declarations and loop statements, which are elaborated statically before simulation begins. An example for generating a series of identical branches is:
genvar i;
generate
for (i = 0; i < N; i = i + 1)
begin : series
[branch](/page/Branch) (in + i, in + i + 1) res_branch;
I(res_branch) <+ V(res_branch) / R;
end
endgenerate
genvar i;
generate
for (i = 0; i < N; i = i + 1)
begin : series
[branch](/page/Branch) (in + i, in + i + 1) res_branch;
I(res_branch) <+ V(res_branch) / R;
end
endgenerate
This construct unrolls into N independent branches at elaboration time, avoiding runtime overhead while supporting parameter-driven designs. It is especially valuable for modeling distributed systems or parameterized macromodels, though it cannot include dynamic procedural code.[1][5]
Partial derivatives in behavioral models support advanced analyses like sensitivity and noise computations, with the ddx() operator providing symbolic partial derivatives within analog expressions, e.g., gd = ddx(I(d), V(a)) for diode conductance, aiding convergence in non-linear solvers. These tools are integral for high-fidelity behavioral models in RF and power electronics simulations.[1]
Event-driven behaviors in analog blocks introduce discrete-time control to continuous models, using the @(event) construct to trigger actions based on signal crossings, timers, or simulation milestones like initial_step, with restrictions to avoid excessive discontinuities and maintain simulation efficiency. For example:
analog begin
@(timer(0, 1u)) V([reset](/page/Reset)) <+ 1;
@(initial_step) initialize_state();
end
analog begin
@(timer(0, 1u)) V([reset](/page/Reset)) <+ 1;
@(initial_step) initialize_state();
end
This allows modeling of sampled-data systems or periodic resets without full digital extensions, with events like @(cross(V(sig) - thresh, +1)) detecting transitions for switch models. Restrictions ensure events do not introduce discontinuities requiring full Newton-Raphson iterations, maintaining simulation efficiency.[1][5]
Verilog-A supports non-intrusive monitoring through probes and sources, which observe or contribute to nets without altering the core simulation topology. A probe is declared as branch (net1, net2) probe_name;, allowing access to potentials or flows via V(probe_name) or I(probe_name) for logging or analysis. Sources, conversely, use contribution operators like I(source) <+ expression; to inject currents dynamically. System tasks such as $simprobe(net, "label"); enable runtime monitoring, outputting values at converged time points without affecting solver matrices. These features are essential for debugging behavioral models and extracting metrics like power dissipation in complex circuits.[1][5]
Simulation Control
Verilog-A provides a set of system tasks and functions to manage simulation execution, report messages, query time, initialize models, control simulation steps, and generate random distributions, enabling precise interaction with the simulator environment. These mechanisms are essential for halting simulations, enforcing accuracy in analog computations, and supporting statistical analyses without altering core modeling behaviors. All such features are defined within the analog procedural context and adhere to restrictions that prevent interference with continuous-time evaluations.[14]
System tasks for halting simulation include $stop, which suspends execution at the current converged timepoint and optionally outputs diagnostics based on an integer argument n (0 for no output, 1 for time and location, 2 for full statistics); $finish, which terminates the simulation after completing the current solution cycle with similar diagnostic options; and $fatal, which reports a fatal error message and invokes $finish to abort. For messaging, Verilog-A supports severity-based tasks such as $error("message") to report runtime errors, $warning("message") for suppressible warnings, and $info("message") for non-severe informational outputs or assertion failures, allowing models to communicate issues to the user during execution. These tasks are invoked procedurally within analog blocks and do not affect the simulation kernel directly but influence its flow and logging.[14]
Time-related functions facilitate access to the simulation timeline: $abstime returns the absolute simulation time in seconds as a real value, useful for absolute referencing in procedural code, while $realtime provides the current simulation time, though it is deprecated in analog contexts in favor of $abstime for consistency. Analog initial blocks, declared as analog initial begin ... end, execute exactly once at time zero for one-time setup tasks like parameter initialization or variable assignments, but they prohibit contributions, access functions, analog operators, and event controls to avoid disrupting the continuous solver. This construct ensures models start in a defined state without ongoing procedural overhead.[14]
Step control mechanisms allow fine-tuned management of the simulator's time advancement: the event trigger @(timer(expr)) schedules procedural execution at a specified delay expr from the current time or periodically using @(timer(start, period)), enabling timed interventions in analog processes; meanwhile, $bound_step(max_step) limits the simulator's next timestep to no more than max_step seconds, promoting numerical stability and accuracy in regions of rapid signal change, such as around 20 points per oscillation cycle for periodic signals. Distribution functions support probabilistic modeling, with $rdist_normal(seed, mean, standard_deviation [, "type_string"]) generating pseudorandom numbers from a normal (Gaussian) distribution, where seed is an integer initializer, mean and standard_deviation define the distribution parameters, and the optional type_string ("global" or "instance") controls reuse across simulations or instances for Monte Carlo analysis. These tools collectively enable robust control over analog simulation dynamics while maintaining the language's focus on behavioral description.[14]
Usage and Implementation
Several commercial electronic design automation (EDA) tools provide native or integrated support for Verilog-A, enabling analog circuit simulation and behavioral modeling within professional workflows. Cadence's Spectre simulator offers native Verilog-A support through its integration with the Virtuoso ADE environment, allowing users to write, simulate, and verify analog models directly.[22] Synopsys CustomSim supports Verilog-A as part of its Verilog-AMS capabilities, facilitating mixed-signal simulations with SPICE primitives and hierarchical designs.[23] Keysight's Advanced Design System (ADS) incorporates Verilog-A via the Verilog-AMS language reference manual, supporting custom model development and runtime performance comparable to built-in elements.[24]
Open-source alternatives have expanded Verilog-A accessibility, particularly for academic and research applications. ngspice integrates Verilog-A primarily through the OSDI/OpenVAF interface, with ADMS deprecated, translating models for efficient analog simulation.[25] Xyce, developed by Sandia National Laboratories, achieves compliance via the ADMS backend, supporting large-scale SPICE-compatible circuits with Verilog-A extensions.[26] SIMetrix, while commercial, includes open-source elements in its Verilog-A implementation by compiling models to C code using the gcc compiler bundled with MinGW extensions.[27]
Many Verilog-A tools employ a compilation strategy to enhance simulation efficiency, converting behavioral descriptions into C code that interfaces with underlying solvers; for instance, SIMetrix automates this process to mix Verilog-A modules seamlessly with SPICE primitives.[27] This approach ensures high-performance execution in mixed-signal environments without requiring users to manage low-level implementations.
Verilog-A maintains backward compatibility with subsets of Verilog-AMS, promoting interoperability across tools that adhere to the language reference manual. It is widely used in compact model development, aligning with standards from the Compact Model Coalition (CMC), which mandates Verilog-A for standardized device models and provides coding guidelines to ensure portability and reliability.[28]
As of 2025, Verilog-A sees growing adoption in AI-driven EDA workflows for generating behavioral models, leveraging machine learning to automate compact model creation and optimization, though its analog-centric nature limits support for FPGA synthesis, which remains focused on digital hardware description languages.[29][30]
Example Code
To illustrate practical usage of Verilog-A, consider a simple resistor model, which implements Ohm's law to relate voltage and current across two terminals.[1]
verilog
module resistor(p, n);
inout p, n;
electrical p, n;
parameter real r = 1k;
analog I(p, n) <+ V(p, n) / r;
endmodule
module resistor(p, n);
inout p, n;
electrical p, n;
parameter real r = 1k;
analog I(p, n) <+ V(p, n) / r;
endmodule
This code begins with the module declaration module resistor(p, n);, defining the component name and two ports p and n for the resistor terminals. The ports are declared as inout to allow bidirectional signal flow, followed by the discipline assignment electrical p, n;, which specifies the electrical domain for voltage (V) and current (I) quantities. The parameter real r = 1k; introduces a resistance value in kiloohms, defaulting to 1 kΩ and allowing instantiation overrides. Within the analog block, the contribution statement I(p, n) <+ V(p, n) / r; computes the branch current as the voltage difference divided by resistance, using the contribution operator <+ to add this expression to the simulator's nodal equations without overwriting other contributions. In simulation, this model enforces linear behavior, contributing to the system's modified nodal analysis by scaling current linearly with voltage, enabling efficient DC, AC, and transient analyses in analog circuit simulators.[1]
For a more behavioral example incorporating dynamics, an amplifier model can include a gain stage alongside input capacitance to model frequency-dependent effects, using the ddt operator for time derivatives.[1]
verilog
[module](/page/Module) amp(out, in);
inout out, in;
electrical out, in;
[parameter](/page/Parameter) real [Gain](/page/Gain) = 1, Cin = 1p;
analog begin
V(out) <+ [Gain](/page/Gain) * V(in);
I(in) <+ Cin * [ddt](/page/DDT)(V(in));
end
[endmodule](/page/Module)
[module](/page/Module) amp(out, in);
inout out, in;
electrical out, in;
[parameter](/page/Parameter) real [Gain](/page/Gain) = 1, Cin = 1p;
analog begin
V(out) <+ [Gain](/page/Gain) * V(in);
I(in) <+ Cin * [ddt](/page/DDT)(V(in));
end
[endmodule](/page/Module)
The module amp(out, in); declares ports out and in as inout in the electrical discipline. Parameters Gain = 1 sets the voltage amplification factor, while Cin = 1p defines input capacitance in picofarads. In the analog block, V(out) <+ Gain * V(in); contributes output voltage as the scaled input voltage, providing ideal amplification. The statement I(in) <+ Cin * ddt(V(in)); adds a capacitive current contribution at the input, where ddt(V(in)) computes the time derivative of the input voltage, modeling charge storage and introducing a pole in the frequency response. During simulation, the gain stage ensures steady-state voltage scaling, while the ddt-based capacitance affects transient settling and high-frequency roll-off, integrating seamlessly into the solver's state equations for mixed-signal verification.[1]
These examples highlight Verilog-A's compatibility with SPICE-based workflows, where models can be compiled into equivalent subcircuit formats for netlist inclusion, such as through instantiation with .SUBCKT directives or paramset mappings that mimic SPICE model cards.[1]
Comparisons
Verilog HDL is primarily designed for modeling discrete-time digital systems, such as logic gates and finite state machines (FSMs), employing event-driven simulation to handle binary signals and synchronous behaviors.[1] In contrast, Verilog-A focuses on continuous-time analog systems, allowing the specification of differential equations to represent physical phenomena like voltage and current dynamics in circuits.[5] This distinction arises from their foundational purposes: Verilog HDL supports register-transfer level (RTL) design and synthesis for digital hardware, while Verilog-A enables behavioral modeling of analog components through iterative numerical solving.[31]
Both languages share a C-like syntax for core elements, including module declarations, parameter definitions, and procedural structures, facilitating familiarity for users transitioning between them.[5] However, Verilog-A extends this with analog-specific constructs, such as the analog block for encapsulating continuous-time processes and contribution statements using the <+ operator to define relationships between signals without direct assignments.[1] These additions are absent in Verilog HDL, which relies on blocking (=) and non-blocking (<=) assignments for net and register updates.[5]
Verilog-A omits support for digital events, sensitivity lists, and always blocks, restricting it to analog-only procedural flows that execute continuously during simulation.[1] Conversely, Verilog HDL does not include analog operators like idt (time integral) or ddt (time derivative), which are essential for modeling dynamic analog behaviors in Verilog-A.[5] As a result, Verilog-A functions as a specialized extension within the Verilog-AMS framework for mixed-signal designs, but it operates standalone for pure analog verification, whereas Verilog HDL typically requires behavioral wrappers or co-simulation interfaces to incorporate analog elements.[31]
Originating from the 1980s development of Verilog HDL, Verilog-A builds on this heritage to address analog modeling needs.[32]
The following table summarizes key syntactic and applicative differences:
| Aspect | Verilog HDL Example | Verilog-A Example | Primary Use Case Difference |
|---|
| Procedural Block | always @(posedge clk) begin ... end | analog begin ... end | Event-driven digital logic vs. continuous analog processes[1] |
| Signal Contribution | out <= in1 & in2; | V(out) <+ gain * V(in); | Discrete assignments for synthesis vs. nodal contributions for simulation[5] |
| Operators | Logical (&, ` | ), delays (#5`) | Analog (ddt(V(in)), idt(I(out))) |
| Simulation Focus | RTL synthesis and timing verification | Behavioral analog and mixed-signal analysis | Hardware implementation vs. system-level verification[31] |
With C Programming Language
Verilog-A exhibits notable syntactic similarities to the C programming language, particularly in its operators and procedural constructs, which facilitate adoption by C programmers in analog modeling. Arithmetic operators such as addition (+), subtraction (-), multiplication (*), and division (/) directly mirror those in C, as do logical operators like AND (&&) and OR (||).[5] The procedural style within analog blocks resembles C functions, employing familiar control structures including if-else statements and for loops, which follow C-like syntax for initialization, condition, and increment.[5][33]
Despite these parallels, Verilog-A's declarative nature sets it apart from C's imperative paradigm. Contributions to circuit nodes, specified using the <+ operator (e.g., V(out) <+ expression), declare how model behavior affects node potentials or flows in a continuous-time context, rather than imperatively assigning variables as in C.[5] Verilog-A lacks C features like pointers and restricts full control flow constructs, such as loops, in analog contexts to prevent discontinuities in simulation; for instance, variable-based loop limits are disallowed inside analog blocks to maintain smooth behavioral descriptions.[5]
Implementation tools enhance Verilog-A's compatibility with C by compiling models into C code for efficient simulation. The SIMetrix simulator employs a dedicated compiler (va.exe) to translate Verilog-A source into C program code, which is then compiled into a dynamic link library (.sxdev) using GCC, enabling seamless integration with the simulator's solver.[33] Similarly, the ADMS tool generates ready-to-compile C code from Verilog-A descriptions, targeting SPICE-like APIs for compact device models and supporting platforms including Linux and Windows.[34] In extended Verilog-AMS environments, C code can be embedded via the VPI interface, though pure Verilog-A focuses on analog primitives without direct procedural C calls.[5]
Operator precedence and expression evaluation in Verilog-A adhere to C rules, with unary operators holding highest priority, followed by multiplicative operations (*, /, %), additive (+, -), and the conditional ternary (?:) as lowest, promoting an intuitive transition for C developers.[5] However, analog semantics introduce key differences from C's discrete, sequential execution; Verilog-A models operate in a time-continuous domain, where expressions contribute to differential equations solved iteratively by the simulator, unlike C's step-by-step computation.[5]
To illustrate, consider a simple Verilog-A contribution for a voltage-controlled current source:
analog begin
I(out, gnd) <+ gm * V(in, gnd);
end
analog begin
I(out, gnd) <+ gm * V(in, gnd);
end
This declares a continuous contribution to the output current branch. An equivalent C pseudocode snippet, as generated by a compiler like ADMS in a simulation context, might approximate it within the solver's residual function as:
void model_function(double *residual, double V_in, double gm) {
double I_out_contrib = gm * V_in;
residual[I_out_index] += I_out_contrib; // Additive contribution to KCL equation
}
void model_function(double *residual, double V_in, double gm) {
double I_out_contrib = gm * V_in;
residual[I_out_index] += I_out_contrib; // Additive contribution to KCL equation
}
Here, the contribution accumulates into the circuit's Kirchhoff equations, but note the non-equivalence for analog operators like ddt (time derivative). For a capacitor model:
analog begin
I(term, gnd) <+ C * [ddt](/page/DDT)(V(term, gnd));
end
analog begin
I(term, gnd) <+ C * [ddt](/page/DDT)(V(term, gnd));
end
In C pseudocode, ddt cannot be directly translated to a simple derivative due to numerical integration; the compiler might generate:
void capacitor_model(double *residual, double V_term, double C, double dt) {
double dV_dt_approx = (V_term - V_term_prev) / dt; // Backward Euler approximation
residual[I_term_index] += C * dV_dt_approx;
// State update: V_term_prev = V_term;
}
void capacitor_model(double *residual, double V_term, double C, double dt) {
double dV_dt_approx = (V_term - V_term_prev) / dt; // Backward Euler approximation
residual[I_term_index] += C * dV_dt_approx;
// State update: V_term_prev = V_term;
}
This highlights how Verilog-A's ddt relies on the simulator's time-stepping method (e.g., trapezoidal integration), which C code must emulate through discrete approximations, preserving conservation laws absent in standard C programming.[5][34]