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