Introduction to Using Ver0.99

Welcome to the extremely obsoleted instruction manual for Ver0.99. This is in a very rough format and will be improved in later versions. It is only a preliminary reference to this particular implementation of Verilog and is not meant to be a tutorial to programming in the Verilog Hardware Description Language. Most notably, the behavioral extensions are missing from this document.

Table of Contents

Compilation and Installation
Ver: The Structural Verilog Compiler
Language Syntax
Keywords
Signal Names
Comments
Modules. What are they?
Parameters
Primitive Gates
I/O Ports
Wires
Assign Statements
Module Instantiations
Compilation
Using Libraries
Netlist Exporting
The Verilog to VHDL Translator
The Definition of the Language (as implemented)

Compilation and Installation

If you are going to run Ver on a Linux x86 system, you do not have to compile anything as all the necessary files may be found in the bin directory. If these files are not present, you will have to compile it by running the shell script RunMeToCompile, which may be found in the ver099 directory. To clean out the directory, you may run CleanScript to remove all of the executables and object files which the compilation process created. Source code is left behind.

For the most part, the sourcecode in this package is plain vanilla Unix C code and should compile on any Unixlike system. However, the scope analyzer program "Anna" may present some problems on some systems as it relies on BSD signal handling semantics (in the file event.c) which reset themselves after a signal handler has been called. It is beyond the scope of this instructional manual to detail how to compile Anna on recalcitrant OS's. It has been successfully compiled and run under Linux, NetBSD (on a 68K Amiga), and AIX on the RS/6000. It has not been tested under Solaris, however Solaris signal handling is similar to that of Linux, and the same fixes should be applied if Anna presents any problems.

The individual executabless (ver, vsim, anna, gen, cyco) are completely self-contained and do not require any additional data files. As such, they may be moved to any directory that is visible in the shell path.

Ver: The Structural Verilog Compiler

Ver is a subset of the Verilog Hardware Description Language that incorporates the structural elements of the language, but not the behavioral ones. The intent of Ver is to generate netlists in the form of IVF files for a separate logic simulator; Ver itself is not a simulator.

Language Syntax

Some sections will be presented "out of order," and some concepts will be used before defining them as a top-down description of the language follows.

Keywords

The following keywords are recognized by the compiler:

and, assign, buf, bufif0, bufif1, const0, const1, constx, constz, endmodule, highz0, highz1, input, latch, module, nand, nmos, nor, not, notif0, notif1, or, output, parameter, pmos, pull0, pull1, pulldown, pullup, reg, rnmos, rpmos, scalared, strong0, strong1, supply0, supply1, tri0, tri1, tri, triand, trior, vectored, wand, weak0, weak1, wire, wor, xnor, and xor.

At this point in time, the reg behavioral keyword is not supported. It is in the grammar and generates data for the .ivf file, but is not valid for vsim. Use latch instead. And note that this is a structural construct.

Signal Names

Mixed case alphanumeric (along with the underscore character) are permitted. The only restriction is that a signal must not start with a numeric digit.

Comments

Comments are indicated by the sequence // as is used in C++. Anything following a // (to the end of the current line) is ignored by the compiler. Additionally, using the C-like /* ... */ syntax is acceptable and those comments are permitted to be nested.

Modules. What are they?

Modules are the next step up from primitive gates such as and and or. A module is composed of primitive gates, latches, wires, input and output ports, and other modules (via instantiation). Recursive module definitions (e.g., a instantiates b which instantiates a) will flag an error and abort the compiler since recursive definitions cannot be synthesized. The grammar covering the position of the module's innards is as follows:

module:         modulehdr ENDMODULE ;

modulehdr:      modulehdr2p iowbody | modulehdr2p ;

modulehdr2p:    modulehdr2 | modulehdr2 param ; 

modulehdr2:     modulehdr2a  ;

modulehdr2a:    modulehdr3 LP modsignals RP semis |
                modulehdr3 LP RP semis |
                modulehdr3 semis ;

modulehdr3:     MODULE IDENTIFIER ;

iowbody:        iowdecs | iowdecs body | body ;

body:           gates | gates body | gates semis | gates semis body ;

semis:          SEMI | semis SEMI ;

iowdecs:        inputdec iowdecs | outputdec iowdecs |
                inputdec | outputdec | inputdec semis | outputdec semis | 
                inputdec semis iowdecs | outputdec semis iowdecs ;

gates:          latchgate SEMI | assign SEMI |
                wiredec SEMI | regdec SEMI | bufgate SEMI | 
                nmosgate SEMI | pmosgate SEMI |
                bufif0gate SEMI | bufif1gate SEMI |
                notif0gate SEMI | notif1gate SEMI |
                notgate SEMI | xorgate SEMI | xnorgate SEMI |
                andgate SEMI | orgate SEMI | nandgate SEMI |
                norgate SEMI | const0gate SEMI | const1gate SEMI |
                constxgate SEMI | constzgate SEMI | component SEMI ;
Note that parameter is a parameter definition, inputdec and outputdec are input and output definitions respectively. assign is an assignment statement, wire is a wire definition, and component is a component instantion. semis indicates one of more semicolons.


An example is in order:

//
// a cross-coupled nand gate positive edge triggered d-ff
// 19/08/97ajb
//
module dff(q,ck,d);
output q;
input ck,d;

nand#4  (q,x2,qbar),
        (qbar,q,x3),
        (x1,x4,x2),
        (x2,x1,ck),
        (x3,x2,ck,x4),
        (x4,x3,d);

endmodule

Parameters

Parameters are simply numeric values defined immediately after a module header. Any identifier defined as a parameter is substituted for its numerically calculated value. The definition is as follows:
param:          parama paramb ;

parama:         PARAMETER  ;

paramb:         pitems SEMI  ;

pitem:          pitema pitemb ;

pitema:         IDENTIFIER EQ  ;

pitemb:         expression  ;

pitems:         pitem | pitem COMMA pitems ;

The following example shows how they can be used:

/*
   this verilog module models a bus with a select on four different
   output values.  note that a unary reduction "and" on the xnor of
   two bitvectors produces a one when the two vectors are equal.
*/

module bus(sel, o);
parameter
        w=8;

input  [1:0] sel;
output [w-1:0] o;
wire   [w-1:0] o;

bufif1 b0[w-1:0] (o, w'h12, {w{ &(sel^~2'b00) }});
bufif1 b1[w-1:0] (o, w'h34, {w{ &(sel^~2'b01) }});
bufif1 b2[w-1:0] (o, w'h56, {w{ &(sel^~2'b10) }});
bufif1 b3[w-1:0] (o, w'h78, {w{ &(sel^~2'b11) }});

endmodule

Note that specifing parameters across modules and in defparam statements is not supported at this time.


Primitive Gates

The keywords and, buf, bufif0, bufif1, const0, const1, constx, constz latch, nand, nmos, nor, not, notif0, notif1, or, pmos, pulldown, pullup, rnmos, rpmos, xnor, and xor, belong to the primitive gate set that Ver recognizes.

Gate definitions are as follows:

gatename [#delay | #(rise, fall) | #(rise, fall, highimpedance)] (ports) [,(ports) ...];


Some examples:

or (o,a,b);
or #2(o,a,b,c,d,e,f,g,h);
latch #(2,2)(o,i),(o2,i2),(o3,i3);
const1(x),(y);


Spacing is irrelevant. Note that the usual format is a single output followed by a series of inputs. The exceptions to this case are the const gates, which require a single output, and latch which requires one output and one input. (The whole model for the time being is clocked simultaneously with one clock--this is currently being revamped where a latch may be declared as an (output, datapin, clock) tuple. Cyco throws the clockpin information away for the time being. Future versions of cyco will handle multiple clock domains.) not and buf gates may have multiple outputs followed by a single input.

Specifying both rise and fall will cause the gate delay to be the longest of the two. This is because vsim can only handle a single delay value. Additionally, cyco, the cycle simulator throws away all timing information and does a logic simulation only. This would make the creation of sequential logical impossible in designs. For that reason, use latch gates to create storage elements in cyco designs (vsim does not support latches yet).

Drive strengths may also be specified, but none of that information is kept. Note that drive strengths are specified before the delay information in the gate definition.

strength0:      SUPPLY0 | STRONG0 | PULL0 | WEAK0 ;

strength1:      SUPPLY1 | STRONG1 | PULL1 | WEAK1 ;

drivestrength:  LP strength0 COMMA strength1 RP 
                | LP strength1 COMMA strength0 RP 
                | LP strength0 COMMA HIGHZ1 RP 
                | LP strength1 COMMA HIGHZ0 RP 
                | LP HIGHZ1 COMMA strength0 RP 
                | LP HIGHZ0 COMMA strength1 RP  ;

I/O Ports

I/O ports are specified by the keywords input and output. Their syntax is as follows:

input [[start:end]] portname [, portname ...] ;
output
[[start:end]] portname [, portname ...] ;


The italicized brackets are actual brackets required by the syntax and are not to be confused with the brackets which indicate an optional item.

Examples:

input a;
output a,b,c,d;
input [7:0] a,b;
input [0:7] a,b,c;
input [5:7] a;
output [7:7] c;

Inputs and output statements may be freely mixed in any order. They must all be grouped at the top of a module definition in one unit.


Wires

Wires generate signal names and are handled similarly:

wire [[start:end]] portname [, portname ...] ;

Wire types supported are: WIRE, TRI, TRI0, TRI1, WAND, TRIAND, WOR, TRIOR, SUPPLY0, and SUPPLY1.

They may also be optionally specified as vectored or scalared. vectored nets may only be accessed as an indivisible unit. (i.e., the signal name only--individual bits cannot be accessed in it, just the whole vector.)


Assign Statements

Assign statements which propagate signals or are equations are of the form:

assign [#delay | #(rise,fall)] destsignal[s] = sourceexpression;

Note that for the multiple bit assign, the left specified bit of the source goes to the left specified bit of the destination, and the right specified bit of the source goes to the right specified bit of the destination (with the intermediate bits getting assigned likewise). So a statement like:

assign a[7:0] = b[0:7];

will cross the bits from 0..7 to 7..0 just as the statement tells it to do.


For assigns, the operators | (or), ~| (nor), & (and), ~& (nand), ^ (xor), ~^ (xnor), ~ (not), and ! (not) are allowed. Expressions may be parenthesized, so an expression like

assign #6 d[3] = (a[3] & (~ b[3]) & (~ c[2])) |
((~ a[3]) & b[3] & (~ c[2])) |
((~ a[3]) & (~ b[3]) & c[2]) |
(a[3] & b[3] & c[2]);

is permissible. Assign statements may be separated by commas if they have a common delay value. Assigning a value of zero or one cannot be done with the logical operations. (i.e., it must be the only operation on a signal.) If you wish to use a logical operation with constants, you'll have to use the 'b 'o 'h or 'd numeric operators rather than just a number. Therefore, represent 42 as something like 8'd42.
Multiple bit assignments are possible. For example, assign #1 g = a & b will assign a bitwise and of vectors a and b to g if all three are defined as bitvectors. Additionally, working with bitvectors in parts, etc. is possible as shown below:
assign #6 d[0:3] = {
        (a[0] & (~ b[0]) & (~ cin)) |
        ((~ a[0]) & b[0] & (~ cin)) |
        ((~ a[0]) & (~ b[0]) & cin) |
        (a[0] & b[0] & cin),

        (a[1] & (~ b[1]) & (~ c[0])) |
        ((~ a[1]) & b[1] & (~ c[0])) |
        ((~ a[1]) & (~ b[1]) & c[0]) |
        (a[1] & b[1] & c[0]),

        (a[2] & (~ b[2]) & (~ c[1])) |
        ((~ a[2]) & b[2] & (~ c[1])) |
        ((~ a[2]) & (~ b[2]) & c[1]) |
        (a[2] & b[2] & c[1]),

        (a[3] & (~ b[3]) & (~ c[2])) |
        ((~ a[3]) & b[3] & (~ c[2])) |
        ((~ a[3]) & (~ b[3]) & c[2]) |
        (a[3] & b[3] & c[2])
        };

Module Instantiations

Instantiations give hardware description languages a great deal of power. Instead of having to repeatedly specify, say, a D flip-flop, it can be packed into a module and used by a simple module instantiation. The syntax for a module instantiation is as follows:

component:      IDENTIFIER comps ;

comps:          component2 | component2 COMMA comps ;

component2:
	IDENTIFIER LBRACK expression COLON expression RBRACK LP compsignals RP
	| IDENTIFIER LBRACK expression COLON expression RBRACK LP RP
	| IDENTIFIER LBRACK expression COLON expression RBRACK
	| IDENTIFIER LBRACK expression RBRACK LP compsignals RP
	| IDENTIFIER LBRACK expression RBRACK LP RP
	| IDENTIFIER LBRACK expression RBRACK
	| IDENTIFIER LP compsignals RP 
	| IDENTIFIER LP RP 
	| IDENTIFIER
	| LP compsignals RP 
	| LP RP ;

compsignals:    compsignals1 | compsignals2 ;

compsignals2:   DOT IDENTIFIER LP genidcomp RP
                | compsignals2 COMMA DOT IDENTIFIER LP genidcomp RP ;

compsignals1:   genidcomp | compsignals1 COMMA genidcomp ;

genidcomp:      asexpression2 ;

...where an asexpression2 is any valid single or multibit expression, and expression is something that generates a numeric value.

Some examples:

f3mux modx1(x1out, in1, x1r5, x1out, m3, m2, m1, m0, rc[15], clk);

f0mux modx2(x2out, in2, m0, clk);

subtractor88 mody2y1(zeroy2y1, y2y1, y2out, y1out,coy0),
                mody1y2(zeroy1y2, y1y2, y1out, y2out,coy);

badd b[0:7] (c,o[0:7],i1[0:7],{i2[0],{7{i2[1]}}},{1'b0,c[1:7]});

For multiple bit signals, if you do not specify a bit range, the whole vector is passed in the order defined. Whole expressions with concatenations, logic expressions such as & | ~, etc. may be passed as shown above.

Compilation

The compilation process is rather straightforward. Bringing up ver with the -h option shows the options available:

Usage:
------
ver [input filename] [options]

-h[elp] prints this screen
-f name force flatten from module "name" else autodetect
-s supress parse statistics table
-v output vhdl translation to stdio

Input is from stdin if no input filename is specified. Remember this if you type ver and the computer waits and does nothing.

Use -f to force a model to be flattened from the name you specify. This is required if no top level module is present or if you have multiple top-level modules and the compiler guesses wrong.

The -s option keeps parse statistics (I/O port counts, etc.) from being displayed.

The -v option will be explained in the section The Verilog to VHDL Translator.

Here is an example program:

//
// test of assign statements...
// note that the longest rise time in a (rise,fall) pair is used!
// also the wiring delays for temps will equal gate delays!
//
module xor21(x,q,a,b);
output x,q;
input a,b;

assign #(2,1) q=(~a&b)|(a&~b); // calculate it the hard way

xor #(2,1)(x,a,b); // with a gate primitive...

endmodule


Running the compiler by typing ver xor.v -f xor21.v prints the following to the screen:

Ver: Structural Verilog Compiler v0.98 (w)1998 BSI
     Module Name       IP OP TP  Refs Comps Sigs Gates Wires Regs
---------------------- -- -- --  ---- ----- ---- ----- ----- ----
 +xor21                2  2  4   0    0     9    6     1     0   

Encountered 1 module, 0 top level, 0 missing.

Flattening from module : xor21
9 symbols, 6 gates, 1 wires, 0 regs in flattened module : xor21.

Wrote file "xor21.ivf" successfully.  Exiting.



Running the compiler by typing ver xor.v -s -f xor21.v prints the following to the screen:

Ver: Structural Verilog Compiler v0.98 (w)1998 BSI

Flattening from module : xor21
9 symbols, 6 gates, 1 wires, 0 regs in flattened module : xor21.

Wrote file "xor21.ivf" successfully. Exiting.


If a module is a "top level" one (it is instantiated by no other modules and instantiates at least one other module), it will be prefixed with an uppercase T before its name.

Using Libraries

You may optionally analyze to a library by using the -l flag. By adding the line library libname; to your Verilog source, if any modules are not present, they will be grabbed from the lib/libname directory. Note that you may have a comma separated list of names and they are searched in the order specified.

Netlist Exporting

An .ivf file is the output of the compilation process. It is to be read into either vsim or cyco. An explanation of the format is beyond the scope of this manual, however the netlist generated from the xor.v file will be shown for illustrative purposes. Note that all signal names are suffixed with their bit number. If it is a single bit vector, it is zero. Also, "temporaries" generated from parsing of assign statements are prefixed with a !T which is impossible for a user to create.

MX xor21.logic{
MP{xor21/b/0 IN;xor21/a/0 IN;xor21/q/0 OUT;xor21/x/0 OUT;}
}

MF{
FS{xor21/!T3/0 }
FS{xor21/x/0 }
FS{xor21/!T2/0 }
FS{xor21/!T4/0 }
FS{xor21/!T1/0 }
FS{xor21/b/0 }
FS{xor21/!T0/0 }
FS{xor21/q/0 }
FS{xor21/a/0 }
FG NL_GATE.1{NL_GATE 20 I 1 xor21/!T4/0 1 xor21/q/0 }
FG XOR.1{XOR 20 I 2 xor21/a/0 xor21/b/0 1 xor21/x/0 }
FG OR.1{OR 0 I 2 xor21/!T1/0 xor21/!T3/0 1 xor21/!T4/0 }
FG AND.1{AND 0 I 2 xor21/a/0 xor21/!T2/0 1 xor21/!T3/0 }
FG NOT.1{NOT 0 I 1 xor21/b/0 1 xor21/!T2/0 }
FG AND.2{AND 0 I 2 xor21/!T0/0 xor21/b/0 1 xor21/!T1/0 }
FG NOT.2{NOT 0 I 1 xor21/a/0 1 xor21/!T0/0 }
}


The Verilog to VHDL Translator

By using the -v flag on the compilation line, a VHDL translation of your Verilog program will be sent to stdio rather than being written to an ivf output file. Note this feature is highly experimental at this time.

Here is a sample input file:

//
// the everpopular cross-coupled nand gate positive edge triggered d-ff
// 19/08/97ajb
//
module dff(q,ck,d);
output q;
input ck,d;

nand#4  (q,x2,qbar),
        (qbar,q,x3),
        (x1,x4,x2),
        (x2,x1,ck),
        (x3,x2,ck,x4),
        (x4,x3,d);

endmodule
and this is the output generated...
--
-- dff.logic
--
entity dff is port(
	q            : out bit;
	ck           : in  bit;
	d            : in  bit);
end dff;

architecture logic of dff is

signal	x1           : bit;
signal	x2           : bit;
signal	x3           : bit;
signal	x4           : bit;
signal	qbar         : bit;

begin

x4 <= ( d NAND x3 ) after 4 ns ;
x3 <= ( x4 NAND ck NAND x2 ) after 4 ns ;
x2 <= ( ck NAND x1 ) after 4 ns ;
x1 <= ( x2 NAND x4 ) after 4 ns ;
qbar <= ( x3 NAND q ) after 4 ns ;
q <= ( qbar NAND x2 ) after 4 ns ;

end;


The Definition of the Language (as implemented)

As this is in a constant state of flux, it has been removed. "Real" documentation will be forthcoming sometime..for the meantime, looking at the included examples should suffice.


17jan99 bybell@linux-workshop.com / bybell@nc.rr.com