Skip to content

Verilog-A Laplace Transform Analysis

Verilog-A is widely used for analog and mixed-signal behavioral modeling, especially when simulating circuits that include dynamic elements such as filters, amplifiers, sensors, or control systems. Many of these blocks are most efficiently expressed as linear time-invariant (LTI) systems, which are typically modeled using Laplace transforms.

Verilog-A provides built-in Laplace transform functions that allow engineers to define complex transfer functions directly in the s-domain, avoiding the need for differential equation implementation. This enables accurate frequency-domain behavior and efficient transient simulation.

Why Use Laplace in Verilog-A

Instead of writing differential equations manually, Laplace operators give several key advantages:

  • Direct implementation of transfer functions
  • Cleaner and more intuitive behavior for LTI systems
  • Suitable for AC, transient, and stability simulations
  • Allows efficient modeling of higher-order dynamics

Common applications include:

Laplace Transform Functions in Verilog-A

Function Description
laplace_zp(input, z[], p[], k) Zero-pole form
laplace_nd(input, num[], den[]) numerator-denominator form
laplace_zd(input, z[], d[]) zero-denominator form
laplace_np(input, z[], p[], k) numerator-pole form

Example : laplace_zp

In Verilog-A, laplace_zp (Zeros-Poles) is the most efficient way to model complex filters when you already know where the poles and zeros should be located on the complex plane.

`include "disciplines.vams"
`include "constants.vams"

module butterworth_2nd(in, out);
    input in; output out;
    electrical in, out;
    parameter real fc = 1000; // Cutoff frequency in Hz

    real wc, p_re, p_im;

    analog begin
        @(initial_step) begin
            wc = 2 * `M_PI * fc;
            // Calculate real and imaginary parts for 45-degree pole placement
            p_re = -wc / sqrt(2); 
            p_im =  wc / sqrt(2);
        end

        // Syntax: laplace_zp(input, {zeros}, {poles}, gain)
        // No zeros: empty brackets {}
        // Two poles: (p_re + j*p_im) and (p_re - j*p_im)
        V(out) <+ laplace_zp(V(in), {}, {p_re, p_im, p_re, -p_im}, 1.0);
    end
endmodule

Example : laplace_nd

For a simple RC filter, the transfer function is :

$$H(s) = \frac{\frac{\omega_0}{Q}s}{s^2 + \frac{\omega_0}{Q}s + \omega_0^2}$$

Here, num[]={0,w0/Q} and den[]={w0**2,w0/Q,1}.

parameter real f0 = 1M;      // Center frequency
parameter real Q = 10;       // Quality factor
real w0;

analog begin
    w0 = 2 * `M_PI * f0;
    // Numerator: 0*s^0 + (w0/Q)*s^1
    // Denominator: w0^2*s^0 + (w0/Q)*s^1 + 1*s^2
    V(out) <+ laplace_nd(V(in), {0, w0/Q}, {w0**2, w0/Q, 1});
end

Example : laplace_zd

Creating a notch filter with transfer function:

$$H(s)=\cfrac{s^2+\omega{}_o^2}{a_2s^2+a_1s+a_0}$$

`include "disciplines.vams"
`include "constants.vams"

module notch_filter(in, out);
    input in; output out;
    electrical in, out;

    parameter real f0 = 60; // Frequency to block
    parameter real Q = 2;   // Quality factor

    real w0, a0, a1, a2;

    analog begin
        @(initial_step) begin
            w0 = 2 * `M_PI * f0;
            // Denominator coefficients for s^0, s^1, s^2
            a0 = w0**2;
            a1 = w0/Q;
            a2 = 1.0;
        end

        // Zeros: {re1, im1, re2, im2, .. }
        // Zeros: {0, w0} and {0, -w0} -> creates (s^2 + w0^2)
        // Denominator: {a0, a1, a2} -> creates (a2*s^2 + a1*s + a0)
        V(out) <+ laplace_zd(V(in), {0, w0, 0, -w0}, {a0, a1, a2});
    end
endmodule

Example : laplace_np

Creating a bandpass filter:

$$H(s)=\cfrac{s}{(s+p_{re}+jp_{im})(s+p_{re}-jp_{im})}$$

`include "disciplines.vams"
`include "constants.vams"

module bandpass_np(in, out);
    input in; output out;
    electrical in, out;

    parameter real f_center = 1e6; // 1MHz center
    parameter real bandwidth = 1e5; // 100kHz bandwidth

    real p_re, p_im, gain;

    analog begin
        @(initial_step) begin
            // Real part of pole relates to bandwidth
            p_re = -`M_PI * bandwidth;
            // Imaginary part relates to center frequency
            p_im = 2 * `M_PI * f_center;
            gain = 1.0;
        end

        // Numerator: {0, gain} -> represents (0 + gain*s)
        // Poles: Two complex conjugate poles
        V(out) <+ laplace_np(V(in), {0, gain}, {p_re, p_im, p_re, -p_im});
    end
endmodule

First-Order Low-Pass Filter

Transfer function:

$$H(s) = \frac{1}{RCs + 1}$$

Verilog-A code:

parameter real R = 1k;
parameter real C = 1n;

V(out) <+ laplace_nd(V(in), {1}, {R*C, 1});

First-Order High-Pass Filter

$$H(s) = \frac{RCs}{RCs + 1}$$

V(out) <+ laplace_nd(V(in), {R*C, 0}, {R*C, 1});

Zeros can be represented using polynomial coefficients.

Second-Order Band-Pass Filter

$$H(s) = \frac{s}{s^2 + \frac{\omega_0}{Q}s + \omega_0^2}$$

parameter real w0 = 1e6; // center radian frequency
parameter real Q  = 10;

V(out) <+ laplace_nd(V(in),
                     {0, 1},
                     {1, w0/Q, w0**2});

Lead compensator

V(out) <+ laplace_zp(V(in),
                     {-1e3},
                     {-1e4},
                     10);

Predistortion and Stability Applications

Laplace blocks appear often in models for:

  • PLL loop filters
  • Compensation networks
  • Control loops in power converters
  • RF linearization structures

Example: Phase lead/lag shaping to ensure stability in feedback amplifiers.

Implementation in a Complete Model

`include "constants.vams"
`include "disciplines.vams"

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

This model supports both AC sweep and transient signals seamlessly.

Avoid Pure Integrators without DC path

// Bad: s-domain integrator without leakage leads to undefined DC
V(out) <+ laplace_nd(V(in), {1}, {0, 1});
  • Add conductance to ground as shown below:
I(out) <+ 1e-12 * V(out);

This maintains a valid DC reference.

Best Practices Summary

Best Practice Reason
Prefer laplace_nd() for compact models Direct coefficient control
Use laplace_zp() for intuitive filter design Easier specification of poles/zeros
Keep high-frequency poles realistic Avoid artificial gain boosting
Ensure valid DC gain conditions Prevent DC convergence failure
Combine with physical modeling where needed Hybrid accuracy + abstraction