Verilog-AMS: A Personal Reference

In my current role as a design verification engineer, I’m learning Verilog-AMS. I decided to make some notes as I go as a reference for myself. There may be errors in this document; I’m not a Verilog expert. This is just what I’ve gleaned from various online sources.

begin…end Block

Instead of using curly braces (these things: {}) to denote blocks like C/C++ does, Verilog uses the keywords “begin” and “end”.

Procedural Blocks (initial, always, analog)

These three blocks let you do things in-order instead of all-at-once. Outside of these blocks, actions are concurrent. Inside these blocks, actions can be concurrent if certain operators are used but are typically processed one at a time.

You can have multiple initial and always blocks in a module, but you can only have one analog block in a module. All blocks start execution at the same time. initial blocks only run once. always blocks loop forever (like a while(1) {} block in C/C++). analog blocks work like always blocks, except they can contain analog statements. Non-analog statements should be placed in always blocks if possible because this will make the simulation run faster.

Ports

In Verilog, ports are either input or output, and that’s it. Everything is digital. In Verilog-AMS, digital ports are defined as logic, and analog ports are defined as electrical.

Numbers

Numbers follow the format X'YZ. X is the number of bits. Y is either d for decimal, b for binary, o for octal, or h for hexadecimal. Z is the number itself. Example: 8'b1010_1100. Underscores are ignored in numbers.

Parameters and Variables

I don’t know what the parameter keyword means. I think it allows you to assign a value to the variable in the same line. Or maybe it makes the variable a constant. Not sure.

Variables types can be integer or real. real variables can have decimal parts. The size of a variable can be set like this: parameter [6:0]PARAM = 7'd69;.

Events?

I’m not sure what these are really called. They have the syntax @(condition signal) statement. condition can be posedge, negedge, or omitted. If it’s omitted, the event will trigger on any change to the signal. The statement can be either a single statement or a begin...end block. A special case of the event syntax is @(*) statement. The * in the sensitivity list lets the compiler analyze the statement and pull out any signals that will cause the output of the statement to change. (If signals A and B cause the output to change, then the compiler will make the sensitivity list A, B.

Assignments

There are several ways to assign signals/parameters to each other. = is a blocking assignment and can only be used in a procedural block. It completes the assignment before the next statement is allowed to execute. This means that B=A; C=B; is equivalent to B=A; C=A;. <= is a non-blocking assignment. The code A<=B; B<=A; is valid and swaps the values of A and B. In analog blocks, the assignment operator <+ is used to transfer analog values.

transition() Function

The transition function is explained well in the “Transition filter” section of the “Verilog-AMS Language Reference Manual” by the Designer’s Guide. The transition() function should be used whenever the output of an analog block is changed: V(aout) <+ transition(aout_new, td, 5n);. This removes discontinuities and makes it more likely that the simulation will converge.

Sample Programs

It’s always nice to have a few sample programs to refer to. I’m not sure if these programs actually compile, but their syntax looks correct.

Sample Program #1: 4-Bit DAC

The first sample program is a 4-bit digital-to-analog converter from the Wikipedia article on Verilog-AMS.

`include "constants.vams"
`include "disciplines.vams"
// Simple DAC model
module dac_simple(aout, clk, din, vref);

    // Parameters
    parameter integer bits = 4 from [1:24];
    parameter integer td = 1n from[0:inf);  // Processing delay of the DAC

    // Define input/output
    input clk, vref;
    input [bits-1:0] din;
    output aout;

    //Define port types
    logic clk;
    logic [bits-1:0] din;
    electrical  aout, vref;

    // Internal variables
    real aout_new, ref;
    integer i;

    // Change signal in the analog part
    analog begin
        @(initial_step) V(aout) <+ 0; // Set output to 0 when the simulation starts
        @(posedge clk) begin // Change output only for rising clock edge    

            aout_new = 0;
            ref = V(vref);

            for(i=0; i<bits; i=i+1) begin
                ref = ref/2;
                aout_new = aout_new + ref * din[i];
            end
        end 
        V(aout) <+ transition(aout_new, td, 5n); // Get a smoother transition when output level changes
    end
endmodule

Sample Program #2: 4-Bit ADC

The second sample program is a 4-bit analog-to-digital converter from the Wikipedia article on Verilog-AMS.

`include "constants.vams"
`include "disciplines.vams"
// Simple ADC model
module adc_simple(clk, dout, vref, vin);

    // Parameters
    parameter integer bits = 4 from[1:24]; // Number of bits
    parameter integer td = 1 from[0:inf);  // Processing delay of the ADC

    // Define input/output
    input clk, vin, vref;
    output [bits-1:0] dout;

    //Define port types
    electrical vref, vin;
    logic clk;
    reg [bits-1:0] dout;

    // Internal variables   
    real ref, sample;
    integer i;


    initial begin
        dout = 0;
    end

    // Perform sampling in the digital blocks for rising clock edge
    always @(posedge clk) begin

        sample = V(vin);
        ref = V(vref);

        for(i=0; i<bits; i=i+1) begin

            ref = ref/2;

            if(sample > ref) begin
                dout[i] <= #(td) 1;
                sample = sample - ref;
            end
            else
                dout[i] <= #(td) 0;
        end
    end
endmodule

Sample Program #3: AND Gate

The third sample program is a simple AND gate from Andrew Tuline’s “An Introduction to Verilog”.

// And gate
//
module andgate (x1, x2, f);
    input x1, x2;
    output f;
    assign f = x1 & x2;
endmodule

Photo by Yuri Samoilov