Merge pull request #679 from steveicarus/steveicarus/more-documentation
Documentation: Transferring more content from the wiki
This commit is contained in:
commit
27b09f5d72
|
|
@ -13,4 +13,6 @@ Icarus Verilog. The code generator is selected by the "-t" command line flag.
|
||||||
vvp
|
vvp
|
||||||
stub
|
stub
|
||||||
null
|
null
|
||||||
|
vhdl
|
||||||
|
verilog95
|
||||||
|
pcb
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
Using the PCB code generator
|
||||||
|
============================
|
||||||
|
|
||||||
|
The PCB target code generator is designed to allow a user to enter a netlist
|
||||||
|
in Verilog format, then generate input files for the GNU PCB layout program.
|
||||||
|
|
||||||
|
Invocation
|
||||||
|
----------
|
||||||
|
|
||||||
|
The PCB target code generation is invoked with the -tpcb flag to the iverilog
|
||||||
|
command. The default output file, "a.out", contains the generated .PCB
|
||||||
|
file. Use the "-o" flag to set the output file name explicitly. The default
|
||||||
|
output file contains only the elements. To generate a "netlist" file, add the
|
||||||
|
flag "-pnetlist=<path>" command line flag.
|
||||||
|
|
||||||
|
Altogether, this example generates the foo.net and foo.pcb files from the
|
||||||
|
foo.v source file::
|
||||||
|
|
||||||
|
% iverilog -tpcb -ofoo.pcb -pnetlist=foo.net foo.v
|
||||||
|
|
||||||
|
Flags
|
||||||
|
-----
|
||||||
|
|
||||||
|
* -o <path>
|
||||||
|
|
||||||
|
Set the output (pcb) file path
|
||||||
|
|
||||||
|
* -pnetlist=path
|
||||||
|
|
||||||
|
Write a netlist file to the given path.
|
||||||
|
|
||||||
|
Attributes Summary
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Attributes are attached to various constructs using the Verilog "(* *)"
|
||||||
|
attribute syntax.
|
||||||
|
|
||||||
|
* ivl_black_box
|
||||||
|
|
||||||
|
Attached to a module declaration or module instantiation, this indicates
|
||||||
|
that the module is a black box. The code generator will create an element
|
||||||
|
for black box instances.
|
||||||
|
|
||||||
|
Parameters Summary
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Within modules, The PCB code generator uses certain parameters to control
|
||||||
|
details. Parameters may have defaults, and can be overridden using the usual
|
||||||
|
Verilog parameter override syntax. Parameters have preferred types.
|
||||||
|
|
||||||
|
* description (string, default="")
|
||||||
|
|
||||||
|
The "description" is a text string that describes the black box. This string
|
||||||
|
is written into the description field of the PCB Element.
|
||||||
|
|
||||||
|
* value (string, default="")
|
||||||
|
|
||||||
|
The "value" is a text tring that describes some value for the black
|
||||||
|
box. Like the description, the code generator does not interpret this value,
|
||||||
|
other then to write it to the appropriate field in the PCB Element."
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
|
||||||
|
Using The Verilog '95 Code Generator
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Icarus Verilog contains a code generator to emit 1995 compliant Verilog from
|
||||||
|
the input Verilog netlist. This allows Icarus Verilog to function as a Verilog
|
||||||
|
> 1995 to Verilog 1995 translator. The main goal of the project was to convert
|
||||||
|
@*, ANSI style arguments and other constructs to something allowed in 1995
|
||||||
|
Verilog.
|
||||||
|
|
||||||
|
Invocation
|
||||||
|
----------
|
||||||
|
|
||||||
|
To translate a Verilog program to 1995 compliant Verilog, invoke "iverilog"
|
||||||
|
with the -tvlog95 flag::
|
||||||
|
|
||||||
|
% iverilog -tvlog95 -o my_design_95.v my_design.v
|
||||||
|
|
||||||
|
The generated Verilog will be placed in a single file (a.out by default), even
|
||||||
|
if the input Verilog is spread over multiple files.
|
||||||
|
|
||||||
|
Generator Flags
|
||||||
|
---------------
|
||||||
|
|
||||||
|
* -pspacing=N
|
||||||
|
|
||||||
|
Set the indent spacing (the default is 2).
|
||||||
|
|
||||||
|
* -pallowsigned=1
|
||||||
|
|
||||||
|
Allow emitting the various signed constructs as an extension to 1995 Verilog
|
||||||
|
(off by default).
|
||||||
|
|
||||||
|
* -pfileline=1
|
||||||
|
|
||||||
|
Emit the original file and line information as a comment for each generated
|
||||||
|
line (off by default).
|
||||||
|
|
||||||
|
Structures that cannot be converted to 1995 compatible Verilog
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
The following Verilog constructs are not translatable to 1995 compatible Verilog:
|
||||||
|
|
||||||
|
* Automatic tasks or functions.
|
||||||
|
|
||||||
|
* The power operator (**). Expressions of the form (2**N)**<variable> (where N
|
||||||
|
is a constant) can be converter to a shift.
|
||||||
|
|
||||||
|
* Some System Verilog constructs (e.g. final blocks, ++/-- operators,
|
||||||
|
etc.). 2-state variables are converted to 4-state variables.
|
||||||
|
|
||||||
|
Icarus extensions that cannot be translated:
|
||||||
|
|
||||||
|
* Integer constants greater than 32 bits.
|
||||||
|
|
||||||
|
* Real valued nets.
|
||||||
|
|
||||||
|
* Real modulus.
|
||||||
|
|
||||||
|
* Most Verilog-A constructs.
|
||||||
|
|
||||||
|
|
||||||
|
Known Issues and Limitations
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Some things are just not finished and should generate an appropriate
|
||||||
|
warning. Here is a list of the major things that still need to be looked at.
|
||||||
|
|
||||||
|
* There are still a few module instantiation port issues (pr1723367 and
|
||||||
|
partselsynth).
|
||||||
|
|
||||||
|
* inout ports are not converted (tran-VP).
|
||||||
|
|
||||||
|
* Variable selects of a non-zero based vector in a continuous assignment are
|
||||||
|
not converted.
|
||||||
|
|
||||||
|
* There is no support for translating a zero repeat in a continuous
|
||||||
|
assignment. It is currently just dropped.
|
||||||
|
|
||||||
|
* A pull device connected to a signal select is not translated correctly (this
|
||||||
|
may be fixed).
|
||||||
|
|
||||||
|
* L-value indexed part selects with a constant undefined base in a continuous
|
||||||
|
assignment are not translated.
|
||||||
|
|
||||||
|
* Logic gates are not arrayed exactly the same as the input and the instance
|
||||||
|
name is not always the same.
|
||||||
|
|
||||||
|
* The signed support does not generate $signed() or $unsigned() function calls
|
||||||
|
in a continuous assignment expression.
|
||||||
|
|
||||||
|
* The special power operator cases are not converted in a continuous
|
||||||
|
assignment.
|
||||||
|
|
||||||
|
* Currently a signed constant that sets the MSB in an unsigned context will be
|
||||||
|
displayed as a negative value (e.g. bit = 1 translates to bit = -1).
|
||||||
|
|
||||||
|
* Can net arrays, etc. be unrolled?
|
||||||
|
|
||||||
|
* Can generate blocks be converted?
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
|
||||||
|
The VHDL Code Generator (-tvhdl)
|
||||||
|
================================
|
||||||
|
|
||||||
|
Icarus Verilog contains a code generator to emit VHDL from the Verilog
|
||||||
|
netlist. This allows Icarus Verilog to function as a Verilog to VHDL
|
||||||
|
translator.
|
||||||
|
|
||||||
|
Invocation
|
||||||
|
----------
|
||||||
|
|
||||||
|
To translate a Verilog program to VHDL, invoke "iverilog" with the -tvhdl
|
||||||
|
flag::
|
||||||
|
|
||||||
|
% iverilog -t vhdl -o my_design.vhd my_design.v
|
||||||
|
|
||||||
|
The generated VHDL will be placed in a single file (a.out by default), even if
|
||||||
|
the Verilog is spread over multiple files.
|
||||||
|
|
||||||
|
Flags
|
||||||
|
-----
|
||||||
|
|
||||||
|
* -pdebug=1
|
||||||
|
|
||||||
|
Print progress messages as the code generator visits each part of the
|
||||||
|
design.
|
||||||
|
|
||||||
|
* -pdepth=N
|
||||||
|
|
||||||
|
Only output VHDL entities for modules found at depth < N in the
|
||||||
|
hierarchy. N=0, the default, outputs all entities. For example, -pdepth=1
|
||||||
|
outputs only the top-level entity.
|
||||||
|
|
||||||
|
Supported Constructs
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
Limitations
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Signal Values and Resolution
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
There are several cases where the behaviour of the translated VHDL deviates
|
||||||
|
from the source Verilog:
|
||||||
|
|
||||||
|
* The result of division by zero is x in Verilog but raises an exception in
|
||||||
|
VHDL.
|
||||||
|
|
||||||
|
* Similarly, the result of reading past the end of an array in Verilog is x,
|
||||||
|
whereas VHDL raises an exception.
|
||||||
|
|
||||||
|
* Any signal that is driven by two or more processes will have the value
|
||||||
|
'U'. This is the result of the signal resolution function in the
|
||||||
|
std_logic_1164 package.
|
||||||
|
|
||||||
|
Constructs Not Supported
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following Verilog constructs cannot be translated to VHDL:
|
||||||
|
|
||||||
|
* fork and join
|
||||||
|
|
||||||
|
* force and release
|
||||||
|
|
||||||
|
* disable
|
||||||
|
|
||||||
|
* real-valued variables
|
||||||
|
|
||||||
|
* switches
|
||||||
|
|
||||||
|
* hierarchical dereferencing
|
||||||
|
|
||||||
|
Other Limitations
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
* The test expressions in case statements must be constant.
|
||||||
|
|
||||||
|
* Translation of a parameter to a corresponding VHDL generic
|
||||||
|
declaration. Instead the default parameter value is used.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
Command File Format
|
||||||
|
===================
|
||||||
|
|
||||||
|
The basic format of a command file is one source file or compiler argument per
|
||||||
|
line. Command files may also have comments of various form, and options for
|
||||||
|
controlling the compiler.
|
||||||
|
|
||||||
|
Comments
|
||||||
|
--------
|
||||||
|
|
||||||
|
Lines that start with a "#" character are comments. All text after the "#"
|
||||||
|
character, is ignored.
|
||||||
|
|
||||||
|
The "//" character sequence also starts a comment that continues to the end of
|
||||||
|
the line.
|
||||||
|
|
||||||
|
The "/\*" and "\*/" character sequences surround multi-line comments. All the
|
||||||
|
text between the comment start and comment end sequences is ignored, even when
|
||||||
|
that text spans multiple lines. This style of comment does not nest, so a "/\*"
|
||||||
|
sequence within a multi-line comment is probably an error.
|
||||||
|
|
||||||
|
Plus-args
|
||||||
|
---------
|
||||||
|
|
||||||
|
Outside of comments, lines that start with a "+" character are compiler
|
||||||
|
arguments. These are called plusargs but they are not the same as extended
|
||||||
|
arguments passed to the "vvp" command. The supported plusargs are definitively
|
||||||
|
listed in the iverilog manual page.
|
||||||
|
|
||||||
|
The plusargs lines are generally "+<name>+..." where the name is the name of
|
||||||
|
an switch, and the arguments are separated by "+" characters, as in::
|
||||||
|
|
||||||
|
+libext+.v+.V+.ver
|
||||||
|
|
||||||
|
With plusargs lines, the "+" character separates tokens, and not white space,
|
||||||
|
so arguments, which may include file paths, may include spaces. A plusarg line
|
||||||
|
is terminated by the line end.
|
||||||
|
|
||||||
|
The line in the command file may also be a "-y" argument. This works exactly
|
||||||
|
the same as the::
|
||||||
|
|
||||||
|
-y <path>
|
||||||
|
|
||||||
|
argument to the compiler; it declares a library directory. The "-y" syntax is
|
||||||
|
also a shorthand for the "+libdir" plusarg, which is a more general form::
|
||||||
|
|
||||||
|
+libdir+<path>...
|
||||||
|
|
||||||
|
File Names
|
||||||
|
----------
|
||||||
|
|
||||||
|
Any lines that are not comments, compiler arguments or plusargs are taken by
|
||||||
|
the compiler to be a source file. The path can contain any characters (other
|
||||||
|
then comment sequences) including blanks, although leading and trailing white
|
||||||
|
space characters are stripped. The restriction of one file name per line is in
|
||||||
|
support of operating systems that can name files any which way. It is not
|
||||||
|
appropriate to expect white spaces to separate file names.
|
||||||
|
|
||||||
|
Variable Substitution
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The syntax "$(name)" is a variable reference, and may be used anywhere within
|
||||||
|
filenames or directory names. The contents of the variable are read from the
|
||||||
|
environment and substituted in place of the variable reference. In Windows,
|
||||||
|
these environment variables are the very same variables that are set through
|
||||||
|
the Control Panel->System dialog box, and in UNIX these variables are
|
||||||
|
environment variables as exported by your shell.
|
||||||
|
|
||||||
|
Variables are useful for giving command files some installation
|
||||||
|
independence. For example, one can import a vendor library with the line::
|
||||||
|
|
||||||
|
-y $(VENDOR)/verilog/library
|
||||||
|
|
||||||
|
in the command file, and the next programmer will be able to use this command
|
||||||
|
file without editing it to point to the location of VENDOR on his
|
||||||
|
machine. Note the use of forward slashes as a directory separator. This works
|
||||||
|
even under Windows, so always use forward slashes in file paths and Windows
|
||||||
|
and UNIX users will be able to share command files.
|
||||||
|
|
||||||
|
An Example
|
||||||
|
----------
|
||||||
|
|
||||||
|
This sample::
|
||||||
|
|
||||||
|
# This is a comment in a command file.
|
||||||
|
# The -y statement declares a library
|
||||||
|
# search directory
|
||||||
|
-y $(PROJ_LIBRARY)/prims
|
||||||
|
#
|
||||||
|
# This plusarg tells the compiler that
|
||||||
|
# files in libraries may have .v or .vl
|
||||||
|
# extensions.
|
||||||
|
+libext+.v+.vl
|
||||||
|
#
|
||||||
|
main.v // This is a source file
|
||||||
|
#
|
||||||
|
# This is a file name with blanks.
|
||||||
|
C:/Project Directory/file name.vl
|
||||||
|
|
||||||
|
is a command file that demonstrates the major syntactic elements of command
|
||||||
|
files. It demonstrates the use of comments, variables, plusargs and file
|
||||||
|
names. It contains a lot of information about the hypothetical project, and
|
||||||
|
suggests that command files can be used to describe the project as a whole
|
||||||
|
fairly concisely.
|
||||||
|
|
||||||
|
The syntax of command files is rich enough that they can be used to document
|
||||||
|
and control the assembly and compilation of large Verilog programs. It is not
|
||||||
|
unusual to have command files that are hundreds of lines long, although
|
||||||
|
judicious use of libraries can lead to very short command files even for large
|
||||||
|
designs. It is also practical to have different command files that pull
|
||||||
|
together combinations of sources and compiler arguments to make different
|
||||||
|
designs from the same Verilog source files.
|
||||||
|
|
||||||
|
Summary
|
||||||
|
-------
|
||||||
|
|
||||||
|
Given the above description of the command file format, the following is a
|
||||||
|
list of the special records with their meaning.
|
||||||
|
|
||||||
|
* +libdir+*dir-path*
|
||||||
|
|
||||||
|
Specify directories to be searched for library modules. The *dir-path* can
|
||||||
|
have multiple directories, separated by "+" characters.
|
||||||
|
|
||||||
|
* +libdir-nocase+dir-path
|
||||||
|
|
||||||
|
This is the same as "+libdir+", but when searching "nocase" libraries for
|
||||||
|
module files, case will not be taken as significant. This is useful when the
|
||||||
|
library is on a case insensitive file system.
|
||||||
|
|
||||||
|
* +libext+*suffix-string*
|
||||||
|
|
||||||
|
Declare the suffix strings to use when searching library directories for
|
||||||
|
Verilog files. The compiler may test a list of suffix strings to support a
|
||||||
|
variety of naming conventions.
|
||||||
|
|
||||||
|
* -y dir-path
|
||||||
|
|
||||||
|
This is like "+libdir+" but each line takes only one path. Like "+libdir+"
|
||||||
|
there can be multiple "-y" records to declare multiple library
|
||||||
|
directories. This is similar to the "-y" flag on the iverilog command line.
|
||||||
|
|
||||||
|
* -v *file-name* or -l *file-name*
|
||||||
|
|
||||||
|
This declares a library file. A library file is just like any other Verilog
|
||||||
|
source file, except that modules declared within it are not implicitly
|
||||||
|
possible root modules.
|
||||||
|
|
||||||
|
NOTE: The "-l" alias is new as of 2 October 2016. It will become available
|
||||||
|
in releases and snapshots made after that date.
|
||||||
|
|
||||||
|
* +incdir+*include-dir-path*
|
||||||
|
|
||||||
|
Declare a directory or list of directories to search for files included by
|
||||||
|
the "include" compiler directive. The directories are searched in
|
||||||
|
order. This is similar to the "-I" flag on the iverilog command line.
|
||||||
|
|
||||||
|
* +define+*name=value*
|
||||||
|
|
||||||
|
Define the preprocessor symbol "name" to have the string value "value". If
|
||||||
|
the value (and the "=") are omitted, then it is assumed to be the string
|
||||||
|
"1". This is similar to the "-D" on the iverilog command line.
|
||||||
|
|
||||||
|
* +timescale+*units/precision*
|
||||||
|
|
||||||
|
Define the default timescale. This is the timescale that is used if there is
|
||||||
|
no other timescale directive in the Verilog source. The compiler default
|
||||||
|
default is "+timescale+1s/1s", which this command file setting can
|
||||||
|
change. The format of the units/precision is the same as that for the
|
||||||
|
timescale directive in the verilog source.
|
||||||
|
|
||||||
|
* +toupper-filename
|
||||||
|
|
||||||
|
This token causes file names after this in the command file to be translated
|
||||||
|
to uppercase. this helps with situations where a directory has passed
|
||||||
|
through a DOS machine (or a FAT file system) and in the process the file
|
||||||
|
names become munged. This is not meant to be used in general, but only in
|
||||||
|
emergencies.
|
||||||
|
|
||||||
|
* +tolower-filename
|
||||||
|
|
||||||
|
The is the lowercase version of "+toupper-filename".
|
||||||
|
|
||||||
|
* +parameter+*name=value*
|
||||||
|
|
||||||
|
This token causes the compiler to override a parameter value for a top-level
|
||||||
|
module. For example, if the module main has the parameter WIDTH, set the
|
||||||
|
width like this "+parameter+main.WIDTH=5". Note the use of the complete
|
||||||
|
hierarchical name. This currently only works for parameters defined in root
|
||||||
|
(top level) modules and a defparam may override the command file value.
|
||||||
|
|
||||||
|
* +vhdl-work+*path*
|
||||||
|
|
||||||
|
When compiling VHDL, this token allows control over the directory to use for
|
||||||
|
holding working package declarations. For example, "+vhdl-work+workdir" will
|
||||||
|
cause the directory "workdir" to be used as a directory for holding working
|
||||||
|
working copies of package headers.
|
||||||
|
|
@ -8,7 +8,12 @@ Icarus Verilog.
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
installation
|
||||||
getting_started
|
getting_started
|
||||||
|
simulation
|
||||||
command_line_flags
|
command_line_flags
|
||||||
|
command_files
|
||||||
verilog_attributes
|
verilog_attributes
|
||||||
vvp_flags
|
vvp_flags
|
||||||
|
vpi
|
||||||
|
ivl_target
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
|
||||||
|
Installation Guide
|
||||||
|
==================
|
||||||
|
|
||||||
|
Icarus Verilog may be installed from source code, or from pre-packaged binary
|
||||||
|
distributions. If you don't have need for the very latest, and prepackaged
|
||||||
|
binaries are available, that would be the best place to start.
|
||||||
|
|
||||||
|
Installation From Source
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Icarus is developed for Unix-like environments but can also be compiled on
|
||||||
|
Windows systems using the Cygwin environment or MinGW compilers. The following
|
||||||
|
instructions are the common steps for obtaining the Icarus Verilog source,
|
||||||
|
compiling and installing. Note that there are precompiled and/or prepackaged
|
||||||
|
versions for a variety of systems, so if you find an appropriate packaged
|
||||||
|
version, then that is the easiest way to install.
|
||||||
|
|
||||||
|
The source code for Icarus is stored under the git source code control
|
||||||
|
system. You can use git to get the latest development head or the latest of a
|
||||||
|
specific branch. Stable releases are placed on branches, and in particular v11
|
||||||
|
stable releases are on the branch "v11-branch" To get the development version
|
||||||
|
of the code follow these steps::
|
||||||
|
|
||||||
|
% git config --global user.name "Your Name Goes Here"
|
||||||
|
% git config --global user.email you@yourpublicemail.example.com
|
||||||
|
% git clone https://github.com/steveicarus/iverilog.git
|
||||||
|
|
||||||
|
The first two lines are optional and are used to tell git who you are. This
|
||||||
|
information is important if/when you submit a patch. We suggest that you add
|
||||||
|
this information now so you don't forget to do it later. The clone will create
|
||||||
|
a directory, named iverilog, containing the source tree, and will populate
|
||||||
|
that directory with the most current source from the HEAD of the repository.
|
||||||
|
|
||||||
|
Change into this directory using::
|
||||||
|
|
||||||
|
% cd iverilog
|
||||||
|
|
||||||
|
Normally, this is enough as you are now pointing at the most current
|
||||||
|
development code, and you have implicitly created a branch "master" that
|
||||||
|
tracks the development head. However, If you want to actually be working on
|
||||||
|
the v11-branch (the branch where the latest v11 patches are) then you checkout
|
||||||
|
that branch with the command::
|
||||||
|
|
||||||
|
% git checkout --track -b v11-branch origin/v11-branch
|
||||||
|
|
||||||
|
This creates a local branch that tracks the v11-branch in the repository, and
|
||||||
|
switches you over to your new v11-branch. The tracking is important as it
|
||||||
|
causes pulls from the repository to re-merge your local branch with the remote
|
||||||
|
v11-branch. You always work on a local branch, then merge only when you
|
||||||
|
push/pull from the remote repository.
|
||||||
|
|
||||||
|
Now that you've cloned the repository and optionally selected the branch you
|
||||||
|
want to work on, your local source tree may later be synced up with the
|
||||||
|
development source by using the git command::
|
||||||
|
|
||||||
|
% git pull
|
||||||
|
|
||||||
|
The git system remembers the repository that it was cloned from, so you don't
|
||||||
|
need to re-enter it when you pull.
|
||||||
|
|
||||||
|
Finally, configuration files are built by the extra step::
|
||||||
|
|
||||||
|
% sh autoconf.sh
|
||||||
|
|
||||||
|
The source is then compiled as appropriate for your system. See the specific
|
||||||
|
build instructions below for your operation system for what to do next.
|
||||||
|
|
||||||
|
You will need autoconf and gperf installed in order for the script to work.
|
||||||
|
If you get errors such as::
|
||||||
|
|
||||||
|
Autoconf in root...
|
||||||
|
autoconf.sh: 10: autoconf: not found
|
||||||
|
Precompiling lexor_keyword.gperf
|
||||||
|
autoconf.sh: 13: gperf: not found.
|
||||||
|
|
||||||
|
You will need to install download and install the autoconf and gperf tools.
|
||||||
|
|
||||||
|
Icarus Specific Configuration Options
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Icarus takes many of the standard configuration options and those will not be
|
||||||
|
described here. The following are specific to Icarus::
|
||||||
|
|
||||||
|
--enable-suffix[=suffix]
|
||||||
|
|
||||||
|
This option allows the user to build Icarus with a default suffix or when
|
||||||
|
provided a user defined suffix. Older stable releases have this flag on by
|
||||||
|
default e.g.(V0.8 by default will build with a "-0.8" suffix). All versions
|
||||||
|
have an appropriate default suffix ("-<base_version>").
|
||||||
|
|
||||||
|
All programs or directories are tagged with this suffix. e.g.(iverilog-0.8,
|
||||||
|
vvp-0.8, etc.). The output of iverilog will reference the correct run time
|
||||||
|
files and directories. The run time will check that it is running a file with
|
||||||
|
a compatible version e.g.(you can not run a V0.9 file with the V0.8 run
|
||||||
|
time). ::
|
||||||
|
|
||||||
|
--with-valgrind
|
||||||
|
|
||||||
|
This option adds extra memory cleanup code and pool management code to allow
|
||||||
|
better memory leak checking when valgrind is available. This option is not
|
||||||
|
need when checking for basic errors with valgrind.
|
||||||
|
|
||||||
|
Compiling on Linux/Unix
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
(Note: You will need to install bison, flex, g++ and gcc) This is probably the
|
||||||
|
easiest case. Given that you have the source tree from the above instructions,
|
||||||
|
the compile and install is generally as simple as::
|
||||||
|
|
||||||
|
% ./configure
|
||||||
|
% make
|
||||||
|
(su to root)
|
||||||
|
# make install
|
||||||
|
|
||||||
|
The "make install" typically needs to be done as root so that it can install
|
||||||
|
in directories such as "/usr/local/bin" etc. You can change where you want to
|
||||||
|
install by passing a prefix to the "configure" command::
|
||||||
|
|
||||||
|
% ./configure --prefix=/my/special/directory
|
||||||
|
|
||||||
|
This will configure the source for eventual installation in the directory that
|
||||||
|
you specify. Note that "rpm" packages of binaries for Linux are typically
|
||||||
|
configured with "--prefix=/usr" per the Linux File System Standard.
|
||||||
|
|
||||||
|
Make sure you have the latest version of flex otherwise you will get an error
|
||||||
|
when parsing lexor.lex.
|
||||||
|
|
||||||
|
Compiling on Macintosh OS X
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Since Mac OS X is a BSD flavor of Unix, you can install Icarus Verilog from
|
||||||
|
source using the procedure described above. You need to install the Xcode
|
||||||
|
software, which includes the C and C++ compilers for Mac OS X. The package is
|
||||||
|
available for free download from Apple's developer site. Once Xcode is
|
||||||
|
installed, you can build Icarus Verilog in a terminal window just like any
|
||||||
|
other Unix install.
|
||||||
|
|
||||||
|
For versions newer than 10.3 the GNU Bison tool (packaged with Xcode) needs to
|
||||||
|
be updated to version 3. ::
|
||||||
|
|
||||||
|
brew install bison
|
||||||
|
echo 'export PATH="/usr/local/opt/bison/bin:$PATH"' >> ~/.bash_profile
|
||||||
|
|
||||||
|
Icarus Verilog is also available through the Homebrew package manager: "brew
|
||||||
|
install icarus-verilog".
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
|
||||||
|
Loadable Target API (ivl_target.h)
|
||||||
|
==================================
|
||||||
|
|
||||||
|
In addition to the standard VPI API, Icarus Verilog supports a non-standard
|
||||||
|
loadable target module API. This API helps C programmers write modules that
|
||||||
|
Icarus Verilog can use to generate code. These modules are used at compile
|
||||||
|
time to write the elaborated design to the simulation or netlist files. For
|
||||||
|
example, the vvp code generator is a loadable target module that writes vvp
|
||||||
|
code into the specified file.
|
||||||
|
|
||||||
|
Loadable target modules gain access to the 'elaborated' design. That means,
|
||||||
|
the source files have been checked for syntax and correctness, any synthesis
|
||||||
|
and general optimization steps have been performed, and what is left is a
|
||||||
|
design that reflects but is not exactly the same as the input Verilog source
|
||||||
|
code. This relieves the modules of the burden of supporting all the odd
|
||||||
|
corners and complexities of the Verilog language.
|
||||||
|
|
||||||
|
The Target Module API
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The API is defined in the header file "ivl_target.h" which is installed with
|
||||||
|
Icarus Verilog. The header defines the functions that the module writer can
|
||||||
|
use to get at the elaborated design during the course of writing the output
|
||||||
|
format.
|
||||||
|
|
||||||
|
The target module API function "target_design" is special in that the API does
|
||||||
|
not provide this function: The target module itself provides it. When the
|
||||||
|
compiler loads the target module, it invokes the "target_design" function with
|
||||||
|
a handle to the design. This is the point where the target module takes over
|
||||||
|
to process the design.
|
||||||
|
|
||||||
|
Compiling Target Modules
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Compiling loadable target modules is similar to compiling VPI modules, in that
|
||||||
|
the module must be compiled with the "-fPIC" flag to gcc, and linked with the
|
||||||
|
"-shared" flag. The module that you compile is then installed in a place where
|
||||||
|
the "iverilog" command can find it, and configuration files are adjusted to
|
||||||
|
account for the new module.
|
||||||
|
|
||||||
|
This code::
|
||||||
|
|
||||||
|
# include <ivl_target.h>
|
||||||
|
|
||||||
|
int target_design(ivl_design_t des)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
is an example module that we can write into the file "empty.c"; and let us
|
||||||
|
compile it into the module file "empty.tgt" like so::
|
||||||
|
|
||||||
|
% gcc -o empty.tgt -fpic -shared empty.c
|
||||||
|
|
||||||
|
This makes the "empty.tgt" file an a dynamically loaded shared object.
|
||||||
|
|
||||||
|
Creating the Target Config File
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The target config file tells the Icarus Verilog core how to process your new
|
||||||
|
code generator. The ivl core expects two configuration files: the name.conf
|
||||||
|
and the name-s.config files. The "-s" version is what is used if the user
|
||||||
|
gives the "-S" (synthesis) flag on the command line.
|
||||||
|
|
||||||
|
The stub target, included in most distributions, demonstrates the config
|
||||||
|
files. The "stub.conf" file is::
|
||||||
|
|
||||||
|
functor:cprop
|
||||||
|
functor:nodangle
|
||||||
|
-t:dll
|
||||||
|
flag:DLL=stub.tgt
|
||||||
|
|
||||||
|
and the "stub-s.conf" file is::
|
||||||
|
|
||||||
|
functor:synth2
|
||||||
|
functor:synth
|
||||||
|
functor:syn-rules
|
||||||
|
functor:cprop
|
||||||
|
functor:nodangle
|
||||||
|
-t:dll
|
||||||
|
flag:DLL=stub.tgt
|
||||||
|
|
||||||
|
Note that the "stub-s.conf" file contains more lines to invoke internal
|
||||||
|
synthesis functions, whereas the "stub.conf" invokes only the basic
|
||||||
|
optimization steps.
|
||||||
|
|
||||||
|
In general, only the last line (The "flag:DLL=<name>.tgt" record) varies for
|
||||||
|
each target. For your target, replace the <name> with the name of your target
|
||||||
|
and you have a configuration file ready to install. Note that this is the name
|
||||||
|
of your target module. This is in fact how the config file tells the compiler
|
||||||
|
the name of your module.
|
||||||
|
|
||||||
|
The rest of the config file is best taken as boiler plate and installed as is,
|
||||||
|
with one difference. If your target is a synthesis target (for example a mosis
|
||||||
|
code generator or a pld code generator) that expects synthesis to happen, then
|
||||||
|
it makes the most sense to create both your config file like the "stub-s.conf"
|
||||||
|
config file. This causes the compiler to do synthesis for your target whether
|
||||||
|
the user gives the "-S" flag or not.
|
||||||
|
|
||||||
|
Installing the Target Module
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Finally, the "empty.conf", the "empty-s.conf" and the "empty.tgt" files need
|
||||||
|
to be installed. Where they go depends on your system, but in Linux they are
|
||||||
|
normally installed in "/usr/lib/ivl".
|
||||||
|
|
@ -0,0 +1,487 @@
|
||||||
|
|
||||||
|
Simulation Using Icarus Verilog
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Simulation is the process of creating models that mimic the behavior of the
|
||||||
|
device you are designing (simulation models) and creating models to exercise
|
||||||
|
the device (test benches). The simulation model need not reflect any
|
||||||
|
understanding of the underlying technology, and the simulator need not know
|
||||||
|
that the design is intended for any specific technology.
|
||||||
|
|
||||||
|
The Verilog simulator, in fact, is usually a different program than the
|
||||||
|
synthesizer. It may even come from a different vendor. The simulator need not
|
||||||
|
know of or generate netlists for the target technology, so it is possible to
|
||||||
|
write one simulator that can be used to model designs intended for a wide
|
||||||
|
variety of technologies. A synthesizer, on the other hand, does need to know a
|
||||||
|
great deal about the target technology in order to generate efficient
|
||||||
|
netlists. Synthesizers are often technology specific and come from vendors
|
||||||
|
with specialized knowledge, whereas simulators are more general purpose.
|
||||||
|
|
||||||
|
Simulation models and test benches, therefore, can use the full range of
|
||||||
|
Verilog features to model the intended design as clearly as possible. This is
|
||||||
|
the time to test the algorithms of the design using language that is
|
||||||
|
relatively easy for humans to read. The simulator, along with the test bench,
|
||||||
|
can test that the clearly written model really does behave as intended, and
|
||||||
|
that the intended behavior really does meet expectations.
|
||||||
|
|
||||||
|
The test benches model the world outside the design, so they are rarely
|
||||||
|
destined for real hardware. They are written in Verilog simply as a matter of
|
||||||
|
convenience, and sometimes they are not written in Verilog at all. The test
|
||||||
|
benches are not throw-away code either, as they are used to retest the device
|
||||||
|
under test as it is transformed from a simulation model to a synthesizeable
|
||||||
|
description.
|
||||||
|
|
||||||
|
Compilation and Elaboration
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Simulation of a design amounts to compiling and executing a program. The
|
||||||
|
Verilog source that represents the simulation model and the test bench is
|
||||||
|
compiled into an executable form and executed by a simulation
|
||||||
|
engine. Internally, Icarus Verilog divides the compilation of program source
|
||||||
|
to an executable form into several steps, and basic understanding of these
|
||||||
|
steps helps understand the nature of failures and errors. The first step is
|
||||||
|
macro preprocessing, then compilation, elaboration, optional optimizations and
|
||||||
|
finally code generation. The boundary between these steps is often blurred,
|
||||||
|
but this progression remains a useful model of the compilation process.
|
||||||
|
|
||||||
|
The macro preprocessing step performs textual substitutions of macros defined
|
||||||
|
with "\`define" statements, textual inclusion with "\`include" statements, and
|
||||||
|
conditional compilation by "\`ifdef" and "\`ifndef" statements. The
|
||||||
|
macropreprocessor for Icarus Verilog is internally a separate program that can
|
||||||
|
be accessed independently by using the "-E" flag to the "iverilog" command,
|
||||||
|
like so::
|
||||||
|
|
||||||
|
% iverilog -E -o out.v example.v
|
||||||
|
|
||||||
|
This command causes the input Verilog file "example.v" to be preprocessed, and
|
||||||
|
the output, a Verilog file without preprocessor statements, written into
|
||||||
|
"out.v". The "\`include" and "\`ifdef" directives in the input file are interpreted,
|
||||||
|
and defined macros substituted, so that the output, a single file, is the same
|
||||||
|
Verilog but with the preprocessor directives gone. All the explicitly
|
||||||
|
specified source files are also combined by the preprocessor, so that the
|
||||||
|
preprocessed result is a single Verilog stream.
|
||||||
|
|
||||||
|
Normally, however, the "-E" flag is not used and the preprocessed Verilog is
|
||||||
|
instead sent directly to the next step, the compiler. The compiler core takes
|
||||||
|
as input preprocessed Verilog and generates an internal parsed form. The
|
||||||
|
parsed form is an internal representation of the Verilog source, in a format
|
||||||
|
convenient for further processing, and is not accessible to the user.
|
||||||
|
|
||||||
|
The next step, elaboration, takes the parsed form, chooses the root modules,
|
||||||
|
and instantiates (makes *instances* of) those roots. The root instances may
|
||||||
|
contain instances of other modules, which may in turn contain instances of yet
|
||||||
|
other modules. The elaboration process creates a hierarchy of module instances
|
||||||
|
that ends with primitive gates and statements.
|
||||||
|
|
||||||
|
Note that there is a difference between a module and a module instance. A
|
||||||
|
module is a type. It is a description of the contents of module instances that
|
||||||
|
have its type. When a module is instantiated within another module, the module
|
||||||
|
name identifies the type of the instance, and the instance name identifies the
|
||||||
|
specific instance of the module. There can be many instances of any given
|
||||||
|
module.
|
||||||
|
|
||||||
|
Root modules are a special case, in that the programmer does not give them
|
||||||
|
instance names. Instead, the instance names of root modules are the same as
|
||||||
|
the name of the module. This is valid because, due to the nature of the
|
||||||
|
Verilog syntax, a module can be a root module only once, so the module name
|
||||||
|
itself is a safe instance name.
|
||||||
|
|
||||||
|
Elaboration creates a hierarchy of scopes. Each module instance creates a new
|
||||||
|
scope within its parent module, with each root module starting a
|
||||||
|
hierarchy. Every module instance in the elaborated program has a unique scope
|
||||||
|
path, a hierarchical name, that starts with its root scope and ends with its
|
||||||
|
own instance name. Every named object, including variables, parameters, nets
|
||||||
|
and gates, also has a hierarchical name that starts with a root scope and ends
|
||||||
|
with its own base name. The compiler uses hierarchical names in error messages
|
||||||
|
generated during or after elaboration, so that erroneous items can be
|
||||||
|
completely identified. These hierarchical names are also used by waveform
|
||||||
|
viewers that display waveform output from simulations.
|
||||||
|
|
||||||
|
The elaboration process creates from the parsed form the scope hierarchy
|
||||||
|
including the primitive objects within each scope. The elaborated design then
|
||||||
|
is optimized to reduce it to a more optimal, but equivalent design. The
|
||||||
|
optimization step takes the fully elaborated design and transforms it to an
|
||||||
|
equivalent design that is smaller or more efficient. These optimizations are,
|
||||||
|
for example, forms of constant propagation and dead code elimination. Useless
|
||||||
|
logic is eliminated, and constant expressions are pre-calculated. The
|
||||||
|
resulting design behaves as if the optimizations were not performed, but is
|
||||||
|
smaller and more efficient. The elimination (and spontaneous creation) of
|
||||||
|
gates and statements only affects the programmer when writing VPI modules,
|
||||||
|
which through the API have limited access to the structures of the design.
|
||||||
|
|
||||||
|
Finally, the optimized design, which is still in an internal form not
|
||||||
|
accessible to users, is passed to a code generator that writes the design into
|
||||||
|
an executable form. For simulation, the code generator is selected to generate
|
||||||
|
the vvp format--a text format that can be executed by the simulation
|
||||||
|
engine. Other code generators may be selected by the Icarus Verilog user, even
|
||||||
|
third party code generators, but the vvp code generator is the default for
|
||||||
|
simulation purposes.
|
||||||
|
|
||||||
|
Making and Using Libraries
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Although simple programs may be written into a single source file, this gets
|
||||||
|
inconvenient as the designs get larger. Also, writing the entire program into
|
||||||
|
a single file makes it difficult for different programs to share common
|
||||||
|
code. It therefore makes sense to divide large programs into several source
|
||||||
|
files, and to put generally useful source code files somewhere accessible to
|
||||||
|
multiple designs.
|
||||||
|
|
||||||
|
Once the program is divided into many files, the compiler needs to be told how
|
||||||
|
to find the files of the program. The simplest way to do that is to list the
|
||||||
|
source files on the command line or in a command file. This is for example the
|
||||||
|
best way to divide up and integrate test bench code with the simulation model
|
||||||
|
of the device under test.
|
||||||
|
|
||||||
|
The Macro Preprocessor
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Another technique is to use the macro preprocessor to include library files
|
||||||
|
into a main file. The `include` directive takes the name of a source file to
|
||||||
|
include. The preprocessor inserts the entire contents of the included file in
|
||||||
|
place of the `include` directive. The preprocessor normally looks in the
|
||||||
|
current working directory (the current working directory of the running
|
||||||
|
compiler, and not the directory where the source file is located) for the
|
||||||
|
included file, but the "-I" switch to "iverilog" can add directories to the
|
||||||
|
search locations list. ::
|
||||||
|
|
||||||
|
% iverilog -I/directory/to/search example.v
|
||||||
|
|
||||||
|
It is common to create include directories shared by a set of programs. The
|
||||||
|
preprocessor `include` directive can be used by the individual programs to
|
||||||
|
include the source files that it needs.
|
||||||
|
|
||||||
|
The preprocessor method of placing source code into libraries is general
|
||||||
|
(arbitrary source code can be placed in the included files) but is static, in
|
||||||
|
the sense that the programmer must explicitly include the desired library
|
||||||
|
files. The automatic module library is a bit more constrained, but is
|
||||||
|
automatic.
|
||||||
|
|
||||||
|
Automatic Module Libraries
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
A common use for libraries is to store module definitions that may be of use
|
||||||
|
to a variety of programs. If modules are divided into a single module per
|
||||||
|
file, and the files are named appropriately, and the compiler is told where to
|
||||||
|
look, then the compiler can automatically locate library files when it finds
|
||||||
|
that a module definition is missing.
|
||||||
|
|
||||||
|
For this to work properly, the library files must be Verilog source, they
|
||||||
|
should contain a single module definition, and the files must be named after
|
||||||
|
the module they contain. For example, if the module "AND2" is a module in the
|
||||||
|
library, then it belongs in a file called "AND2.v" and that file contains only
|
||||||
|
the "AND2" module. A library, then, is a directory that contains properly
|
||||||
|
named and formatted source files. ::
|
||||||
|
|
||||||
|
% iverilog -y/library/to/search example.v
|
||||||
|
|
||||||
|
The "-y" flag to "iverilog" tells the compiler to look in the specified
|
||||||
|
directory for library modules whenever the program instantiates a module that
|
||||||
|
is not otherwise defined. The programmer may include several "-y" flags on the
|
||||||
|
command line (or in a command file) and the compiler will search each
|
||||||
|
directory in order until an appropriate library file is found to resolve the
|
||||||
|
module.
|
||||||
|
|
||||||
|
Once a module is defined, either in the program or by reading a library
|
||||||
|
module, the loaded definition is used from then on within the program. If the
|
||||||
|
module is defined within a program file or within an included file, then the
|
||||||
|
included definition is used instead of any library definition. If a module is
|
||||||
|
defined in multiple libraries, then the first definition that the compiler
|
||||||
|
finds is used, and later definitions are never read.
|
||||||
|
|
||||||
|
Icarus Verilog accesses automatic libraries during elaboration, after it has
|
||||||
|
already preprocessed and parsed the non-library source files. Modules in
|
||||||
|
libraries are not candidates for root modules, and are not even parsed unless
|
||||||
|
they are instantiated in other source files. However, a library module may
|
||||||
|
reference other library modules, and reading in a library module causes it to
|
||||||
|
be parsed and elaborated, and further library references resolved, just like a
|
||||||
|
non-library module. The library lookup and resolution process iterates until
|
||||||
|
all referenced modules are resolved, or known to be missing from the
|
||||||
|
libraries.
|
||||||
|
|
||||||
|
The automatic module library technique is useful for including vendor or
|
||||||
|
technology libraries into a program. Many EDA vendors offer module libraries
|
||||||
|
that are formatted appropriately; and with this technique, Icarus Verilog can
|
||||||
|
use them for simulation.
|
||||||
|
|
||||||
|
Advanced Command Files
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Command files were mentioned in the "Getting Started" chapter, but only
|
||||||
|
briefly. In practice, Verilog programs quickly grow far beyond the usefulness
|
||||||
|
of simple command line options, and even the macro preprocessor lacks the
|
||||||
|
flexibility to combine source and library modules according to the advancing
|
||||||
|
development process.
|
||||||
|
|
||||||
|
The main contents of a command file is a list of Verilog source files. You can
|
||||||
|
name in a command file all the source files that make up your design. This is
|
||||||
|
a convenient way to collect together all the files that make up your
|
||||||
|
design. Compiling the design can then be reduced to a simple command line like
|
||||||
|
the following::
|
||||||
|
|
||||||
|
% iverilog -c example.cf
|
||||||
|
|
||||||
|
The command file describes a configuration. That is, it lists the specific
|
||||||
|
files that make up your design. It is reasonable, during the course of
|
||||||
|
development, to have a set of different but similar variations of your
|
||||||
|
design. These variations may have different source files but also many common
|
||||||
|
source files. A command file can be written for each variation, and each
|
||||||
|
command file lists the source file names used by each variation.
|
||||||
|
|
||||||
|
A configuration may also specify the use of libraries. For example, different
|
||||||
|
configurations may be implementations for different technologies so may use
|
||||||
|
different parts libraries. To make this work, command files may include "-y"
|
||||||
|
statements. These work in command files exactly how they work on "iverilog"
|
||||||
|
command line. Each "-y" flag is followed by a directory name, and the
|
||||||
|
directories are searched for library modules in the order that they are listed
|
||||||
|
in the command file.
|
||||||
|
|
||||||
|
The include search path can also be specified in configuration files with
|
||||||
|
"+incdir+" tokens. These tokens start with the "+incdir+" string, then
|
||||||
|
continue with directory paths, separated from each other with "+" characters
|
||||||
|
(not spaces) for the length of the line.
|
||||||
|
|
||||||
|
Other information can be included in the command file. See the section Command
|
||||||
|
File Format for complete details on what can go in a command file.
|
||||||
|
|
||||||
|
Input Data at Runtime
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Often, it is useful to compile a program into an executable simulation, then
|
||||||
|
run the simulation with various inputs. This requires some means to pass data
|
||||||
|
and arguments to the compiled program each time it is executed. For example,
|
||||||
|
if the design models a micro-controller, one would like to run the compiled
|
||||||
|
simulation against a variety of different ROM images.
|
||||||
|
|
||||||
|
There are a variety of ways for a Verilog program to get data from the outside
|
||||||
|
world into the program at run time. Arguments can be entered on the command
|
||||||
|
line, and larger amounts of data can be read from files. The simplest method
|
||||||
|
is to take arguments from the command line.
|
||||||
|
|
||||||
|
Consider this running example of a square root calculator::
|
||||||
|
|
||||||
|
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||||
|
input clk;
|
||||||
|
output rdy;
|
||||||
|
input reset;
|
||||||
|
|
||||||
|
input [31:0] x;
|
||||||
|
output [15:0] acc;
|
||||||
|
|
||||||
|
// acc holds the accumulated result, and acc2 is
|
||||||
|
// the accumulated square of the accumulated result.
|
||||||
|
reg [15:0] acc;
|
||||||
|
reg [31:0] acc2;
|
||||||
|
|
||||||
|
// Keep track of which bit I'm working on.
|
||||||
|
reg [4:0] bitl;
|
||||||
|
wire [15:0] bit = 1 << bitl;
|
||||||
|
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||||
|
|
||||||
|
// The output is ready when the bitl counter underflows.
|
||||||
|
wire rdy = bitl[4];
|
||||||
|
|
||||||
|
// guess holds the potential next values for acc,
|
||||||
|
// and guess2 holds the square of that guess.
|
||||||
|
wire [15:0] guess = acc | bit;
|
||||||
|
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||||
|
|
||||||
|
task clear;
|
||||||
|
begin
|
||||||
|
acc = 0;
|
||||||
|
acc2 = 0;
|
||||||
|
bitl = 15;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial clear;
|
||||||
|
|
||||||
|
always @(reset or posedge clk)
|
||||||
|
if (reset)
|
||||||
|
clear;
|
||||||
|
else begin
|
||||||
|
if (guess2 <= x) begin
|
||||||
|
acc <= guess;
|
||||||
|
acc2 <= guess2;
|
||||||
|
end
|
||||||
|
bitl <= bitl - 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
One could write the test bench as a program that passes a representative set
|
||||||
|
of input values into the device and checks the output result. However, we can
|
||||||
|
also write a program that takes on the command line an integer value to be
|
||||||
|
used as input to the device. We can write and compile this program, then pass
|
||||||
|
different input values on the run time command line without recompiling the
|
||||||
|
simulation.
|
||||||
|
|
||||||
|
This example demonstrates the use of the "$value$plusargs" to access command
|
||||||
|
line arguments of a simulation::
|
||||||
|
|
||||||
|
module main;
|
||||||
|
|
||||||
|
reg clk, reset;
|
||||||
|
reg [31:0] x;
|
||||||
|
wire [15:0] y;
|
||||||
|
wire rdy;
|
||||||
|
|
||||||
|
sqrt32 dut (clk, rdy, reset, x, y);
|
||||||
|
|
||||||
|
always #10 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 0;
|
||||||
|
reset = 1;
|
||||||
|
|
||||||
|
if (! $value$plusargs("x=%d", x)) begin
|
||||||
|
$display("ERROR: please specify +x=<value> to start.");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
#35 reset = 0;
|
||||||
|
|
||||||
|
wait (rdy) $display("y=%d", y);
|
||||||
|
$finish;
|
||||||
|
end // initial begin
|
||||||
|
|
||||||
|
endmodule // main
|
||||||
|
|
||||||
|
The "$value$plusargs" system function takes a string pattern that describes
|
||||||
|
the format of the command line argument, and a reference to a variable that
|
||||||
|
receives the value. The "sqrt_plusargs" program can be compiled and executed
|
||||||
|
like this::
|
||||||
|
|
||||||
|
% iverilog -osqrt_plusargs.vvp sqrt_plusargs.v sqrt.v
|
||||||
|
% vvp sqrt_plusargs.vvp +x=81
|
||||||
|
y= 9
|
||||||
|
|
||||||
|
Notice that the "x=%d" string of the "$value$plusargs" function describes the
|
||||||
|
format of the argument. The "%d" matches a decimal value, which in the sample
|
||||||
|
run is "81". This gets assigned to "x" by the "$value$plusargs" function,
|
||||||
|
which returns TRUE, and the simulation continues from there.
|
||||||
|
|
||||||
|
If two arguments have to be passed to the testbench then the main module would
|
||||||
|
be modified as follows::
|
||||||
|
|
||||||
|
module main;
|
||||||
|
|
||||||
|
reg clk, reset;
|
||||||
|
reg [31:0] x;
|
||||||
|
reg [31:0] z;
|
||||||
|
wire [15:0] y1,y2;
|
||||||
|
wire rdy1,rdy2;
|
||||||
|
|
||||||
|
sqrt32 dut1 (clk, rdy1, reset, x, y1);
|
||||||
|
sqrt32 dut2 (clk, rdy2, reset, z, y2);
|
||||||
|
|
||||||
|
always #10 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 0;
|
||||||
|
reset = 1;
|
||||||
|
|
||||||
|
if (! $value$plusargs("x=%d", x)) begin
|
||||||
|
$display("ERROR: please specify +x=<value> to start.");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (! $value$plusargs("z=%d", z)) begin
|
||||||
|
$display("ERROR: please specify +z=<value> to start.");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#35 reset = 0;
|
||||||
|
|
||||||
|
wait (rdy1) $display("y1=%d", y1);
|
||||||
|
wait (rdy2) $display("y2=%d", y2);
|
||||||
|
$finish;
|
||||||
|
end // initial begin
|
||||||
|
|
||||||
|
endmodule // main
|
||||||
|
|
||||||
|
and the "sqrt_plusargs" program would be compiled and executed as follows::
|
||||||
|
|
||||||
|
% iverilog -osqrt_plusargs.vvp sqrt_plusargs.v sqrt.v
|
||||||
|
% vvp sqrt_plusargs.vvp +x=81 +z=64
|
||||||
|
y1= 9
|
||||||
|
y2= 8
|
||||||
|
|
||||||
|
In general, the "vvp" command that executes the compiled simulation takes a
|
||||||
|
few predefined argument flags, then the file name of the simulation. All the
|
||||||
|
arguments after the simulation file name are extended arguments to "vvp" and
|
||||||
|
are passed to the executed design. Extended arguments that start with a "+"
|
||||||
|
character are accessible through the "$test$plusargs" and "$value$plusargs"
|
||||||
|
system functions. Extended arguments that do not start with a "+" character
|
||||||
|
are only accessible to system tasks and functions written in C using the VPI.
|
||||||
|
|
||||||
|
In the previous example, the program pulls the argument from the command line,
|
||||||
|
assigns it to the variable "x", and runs the sqrt device under test with that
|
||||||
|
value. This program can take the integer square root of any single value. Of
|
||||||
|
course, if you wish to test with a large number of input values, executing the
|
||||||
|
program many times may become tedious.
|
||||||
|
|
||||||
|
Another technique would be to put a set of input values into a data file, and
|
||||||
|
write the test bench to read the file. We can then edit the file to add new
|
||||||
|
input values, then rerun the simulation without compiling it again. The
|
||||||
|
advantage of this technique is that we can accumulate a large set of test
|
||||||
|
input values, and run the lot as a batch.
|
||||||
|
|
||||||
|
This example::
|
||||||
|
|
||||||
|
module main;
|
||||||
|
|
||||||
|
reg clk, reset;
|
||||||
|
reg [31:0] data[4:0];
|
||||||
|
reg [31:0] x;
|
||||||
|
wire [15:0] y;
|
||||||
|
wire rdy;
|
||||||
|
|
||||||
|
sqrt32 dut (clk, rdy, reset, x, y);
|
||||||
|
|
||||||
|
always #10 clk = ~clk;
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
initial begin
|
||||||
|
/* Load the data set from the hex file. */
|
||||||
|
$readmemh("sqrt.hex", data);
|
||||||
|
for (i = 0 ; i <= 4 ; i = i + 1) begin
|
||||||
|
clk = 0;
|
||||||
|
reset = 1;
|
||||||
|
|
||||||
|
x = data[i];
|
||||||
|
|
||||||
|
#35 reset = 0;
|
||||||
|
|
||||||
|
wait (rdy) $display("y=%d", y);
|
||||||
|
end
|
||||||
|
$finish;
|
||||||
|
end // initial begin
|
||||||
|
|
||||||
|
endmodule // main
|
||||||
|
|
||||||
|
demonstrates the use of "$readmemh" to read data samples from a file into a
|
||||||
|
Verilog array. Start by putting into the file "sqrt.hex" the numbers::
|
||||||
|
|
||||||
|
51
|
||||||
|
19
|
||||||
|
1a
|
||||||
|
18
|
||||||
|
1
|
||||||
|
|
||||||
|
Then run the simulation with the command sequence::
|
||||||
|
|
||||||
|
% iverilog -osqrt_readmem.vvp sqrt_readmem.vl sqrt.vl
|
||||||
|
% vvp sqrt_readmem.vvp
|
||||||
|
y= 9
|
||||||
|
y= 5
|
||||||
|
y= 5
|
||||||
|
y= 4
|
||||||
|
y= 1
|
||||||
|
|
||||||
|
It is easy enough to change this program to work with larger data sets, or to
|
||||||
|
change the "data.hex" file to contain different data. This technique is also
|
||||||
|
common for simulating algorithms that take in larger data sets. One can extend
|
||||||
|
this idea slightly by using a "$value$plusargs" statement to select the file
|
||||||
|
to read.
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
|
||||||
|
Using VPI
|
||||||
|
=========
|
||||||
|
|
||||||
|
Icarus Verilog implements a portion of the PLI 2.0 API to Verilog. This allows
|
||||||
|
programmers to write C code that interfaces with Verilog simulations to
|
||||||
|
perform tasks otherwise impractical with straight Verilog. Many Verilog
|
||||||
|
designers, especially those who only use Verilog as a synthesis tool, can
|
||||||
|
safely ignore the entire matter of the PLI (and this chapter) but the designer
|
||||||
|
who wishes to interface a simulation with the outside world cannot escape VPI.
|
||||||
|
|
||||||
|
The rest of this article assumes some knowledge of C programming, Verilog PLI,
|
||||||
|
and of the compiler on your system. In most cases, Icarus Verilog assumes the
|
||||||
|
GNU Compilation System is the compiler you are using, so tips and instructions
|
||||||
|
that follow reflect that. If you are not a C programmer, or are not planning
|
||||||
|
any VPI modules, you can skip this entire article. There are references at the
|
||||||
|
bottom for information about more general topics.
|
||||||
|
|
||||||
|
How It Works
|
||||||
|
------------
|
||||||
|
|
||||||
|
The VPI modules are compiled loadable object code that the runtime loads at
|
||||||
|
the user's request. The user commands vvp to locate and load modules with the
|
||||||
|
"-m" switch. For example, to load the "sample.vpi" module::
|
||||||
|
|
||||||
|
% vvp -msample foo.vvp
|
||||||
|
|
||||||
|
The vvp run-time loads the modules first, before executing any of the
|
||||||
|
simulation, or even before compiling the vvp code. Part of the loading
|
||||||
|
includes invoking initialization routines. These routines register with the
|
||||||
|
run-time all the system tasks and functions that the module implements. Once
|
||||||
|
this is done, the run time loader can match names of the called system tasks
|
||||||
|
of the design with the implementations in the VPI modules.
|
||||||
|
|
||||||
|
(There is a special module, the system.vpi module, that is always loaded to
|
||||||
|
provide the core system tasks.)
|
||||||
|
|
||||||
|
The simulator run time (The "vvp" program) gets a handle on a freshly loaded
|
||||||
|
module by looking for the symbol "vlog_startup_routines" in the loaded
|
||||||
|
module. This table, provided by the module author and compiled into the
|
||||||
|
module, is a null terminated table of function pointers. The simulator calls
|
||||||
|
each of the functions in the table in order. The following simple C definition
|
||||||
|
defines a sample table::
|
||||||
|
|
||||||
|
void (*vlog_startup_routines[])() = {
|
||||||
|
hello_register,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
Note that the "vlog_startup_routines" table is an array of function pointers,
|
||||||
|
with the last pointer a 0 to mark the end. The programmer can organize the
|
||||||
|
module to include many startup functions in this table, if desired.
|
||||||
|
|
||||||
|
The job of the startup functions that are collected in the startup table is to
|
||||||
|
declare the system tasks and functions that the module provides. A module may
|
||||||
|
implement as many tasks/functions as desired, so a module can legitimately be
|
||||||
|
called a library of system tasks and functions.
|
||||||
|
|
||||||
|
Compiling VPI Modules
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
To compile and link a VPI module for use with Icarus Verilog, you must compile
|
||||||
|
all the source files of a module as if you were compiling for a DLL or shared
|
||||||
|
object. With gcc under Linux, this means compiling with the "-fpic" flag. The
|
||||||
|
module is then linked together with the vpi library like so::
|
||||||
|
|
||||||
|
% gcc -c -fpic hello.c
|
||||||
|
% gcc -shared -o hello.vpi hello.o -lvpi
|
||||||
|
|
||||||
|
This assumes that the "vpi_user.h header file and the libvpi.a library file
|
||||||
|
are installed on your system so that gcc may find them. This is normally the
|
||||||
|
case under Linux and UNIX systems. An easier, the preferred method that works
|
||||||
|
on all supported systems is to use the single command::
|
||||||
|
|
||||||
|
% iverilog-vpi hello.c
|
||||||
|
|
||||||
|
The "iverilog-vpi" command takes as command arguments the source files for
|
||||||
|
your VPI module, compiles them with proper compiler flags, and links them into
|
||||||
|
a vpi module with any system specific libraries and linker flags that are
|
||||||
|
required. This simple command makes the "hello.vpi" module with minimum fuss.
|
||||||
|
|
||||||
|
A Worked Example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Let us try a complete, working example. Place the C code that follows into the
|
||||||
|
file hello.c::
|
||||||
|
|
||||||
|
# include <vpi_user.h>
|
||||||
|
|
||||||
|
static int hello_compiletf(char*user_data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hello_calltf(char*user_data)
|
||||||
|
{
|
||||||
|
vpi_printf("Hello, World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hello_register()
|
||||||
|
{
|
||||||
|
s_vpi_systf_data tf_data;
|
||||||
|
|
||||||
|
tf_data.type = vpiSysTask;
|
||||||
|
tf_data.tfname = "$hello";
|
||||||
|
tf_data.calltf = hello_calltf;
|
||||||
|
tf_data.compiletf = hello_compiletf;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.user_data = 0;
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*vlog_startup_routines[])() = {
|
||||||
|
hello_register,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
and place the Verilog code that follows into hello.v::
|
||||||
|
|
||||||
|
module main;
|
||||||
|
initial $hello;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
Next, compile and execute the code with these steps::
|
||||||
|
|
||||||
|
% iverilog-vpi hello.c
|
||||||
|
% iverilog -ohello.vvp hello.v
|
||||||
|
% vvp -M. -mhello hello.vvp
|
||||||
|
Hello, World!
|
||||||
|
|
||||||
|
The compile and link in this example are conveniently combined into the
|
||||||
|
"iverilog-vpi" command. The "iverilog" command then compiles the "hello.v"
|
||||||
|
Verilog source file to the "hello.vvp" program. Next, the "vvp" command
|
||||||
|
demonstrates the use of the "-M" and "-m" flags to specify a vpi module search
|
||||||
|
directory and vpi module name. Specifically, they tell the "vvp" command where
|
||||||
|
to find the module we just compiled.
|
||||||
|
|
||||||
|
The "vvp" command, when executed as above, loads the "hello.vpi" module that
|
||||||
|
it finds in the current working directory. When the module is loaded, the
|
||||||
|
vlog_startup_routines table is scanned, and the "hello_register" function is
|
||||||
|
executed. The "hello_register" function in turn tells "vvp" about the system
|
||||||
|
tasks that are included in this module.
|
||||||
|
|
||||||
|
After the modules are all loaded, the "hello.vvp" design file is loaded and
|
||||||
|
its call to the "$hello" system task is matched up to the version declared by
|
||||||
|
the module. While "vvp" compiles the "hello.vvp" source, any calls to "$hello"
|
||||||
|
are referred to the "compiletf" function. This function is called at compile
|
||||||
|
time and can be used to check parameters to system tasks or function. It can
|
||||||
|
be left empty like this, or left out completely. The "compiletf" function can
|
||||||
|
help performance by collecting parameter checks in compile time, so they do
|
||||||
|
not need to be done each time the system task is run, thus potentially saving
|
||||||
|
execution time overall.
|
||||||
|
|
||||||
|
When the run-time executes the call to the hello system task, the
|
||||||
|
"hello_calltf" function is invoked in the loaded module, and thus the output
|
||||||
|
is generated. The "calltf" function is called at run time when the Verilog
|
||||||
|
code actually executes the system task. This is where the active code of the
|
||||||
|
task belongs.
|
||||||
|
|
||||||
|
System Function Return Types
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Icarus Verilog supports system functions as well as system tasks, but there is
|
||||||
|
a complication. Notice how the module that you compile is only loaded by the
|
||||||
|
"vvp" program. This is mostly not an issue, but elaboration of expressions
|
||||||
|
needs to keep track of types, so the main compiler needs to know the return
|
||||||
|
type of functions.
|
||||||
|
|
||||||
|
Starting with Icarus Verilog v11, the solution is quite simple. The names and
|
||||||
|
locations of the user's VPI modules can be passed to the compiler via the
|
||||||
|
"iverilog" -m and -L flags and the IVERILOG_VPI_MODULE_PATH environment
|
||||||
|
variable. The compiler will load and analyse the specified modules to
|
||||||
|
automatically determine any function return types. The compiler will also
|
||||||
|
automatically pass the names and locations of the specified modules to the
|
||||||
|
"vvp" program, so that they don't need to be specified again on the "vvp"
|
||||||
|
command line.
|
||||||
|
|
||||||
|
For Icarus Verilog versions prior to v11, the solution requires that the
|
||||||
|
developer of a module include the table in a form that the compiler can
|
||||||
|
read. The System Function Table file carries this information. A simple
|
||||||
|
example looks like this::
|
||||||
|
|
||||||
|
# Example sft declarations of some common functions
|
||||||
|
$random vpiSysFuncInt
|
||||||
|
$bitstoreal vpiSysFuncReal
|
||||||
|
$realtobits vpiSysFuncSized 64 unsigned
|
||||||
|
|
||||||
|
This demonstrates the format of the file and support types. Each line contains
|
||||||
|
a comment (starts with "#") or a type declaration for a single function. The
|
||||||
|
declaration starts with the name of the system function (including the leading
|
||||||
|
"$") and ends with the type. The supported types are:
|
||||||
|
|
||||||
|
* vpiSysFuncInt
|
||||||
|
* vpiSysFuncReal
|
||||||
|
* vpiSysFuncSized <wid> <signed|unsigned>
|
||||||
|
|
||||||
|
Any functions that do not have an explicit type declaration in an SFT file are
|
||||||
|
implicitly taken to be "vpiSysFuncSized 32 unsigned".
|
||||||
|
|
||||||
|
The module author provides, along with the ".vpi" file that is the module, a
|
||||||
|
".sft" that declares all the function return types. For example, if the file
|
||||||
|
is named "example.sft", pass it to the "iverilog" command line or in the
|
||||||
|
command file exactly as if it were an ordinary source file.
|
||||||
|
|
||||||
|
Cadence PLI Modules
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
With the cadpli module, Icarus Verilog is able to load PLI1 applications that
|
||||||
|
were compiled and linked to be dynamic loaded by Verilog-XL or
|
||||||
|
NC-Verilog. This allows Icarus Verilog users to run third-party modules that
|
||||||
|
were compiled to interface with XL or NC. Obviously, this only works on the
|
||||||
|
operating system that the PLI application was compiled to run on. For example,
|
||||||
|
a Linux module can only be loaded and run under Linux. In addition, a 64-bit
|
||||||
|
version of vvp can only load 64-bit PLI1 applications, etc.
|
||||||
|
|
||||||
|
Icarus Verilog uses an interface module, the "cadpli" module, to connect the
|
||||||
|
worlds. This module is installed with Icarus Verilog, and is invoked by the
|
||||||
|
usual -m flag to iverilog or vvp. This module in turn scans the extended
|
||||||
|
arguments, looking for -cadpli= arguments. The latter specify the share object
|
||||||
|
and bootstrap function for running the module. For example, to run the module
|
||||||
|
product.so, that has the bootstrap function "my_boot"::
|
||||||
|
|
||||||
|
% vvp -mcadpli a.out -cadpli=./product.so:my_boot
|
||||||
|
|
||||||
|
The "-mcadpli" argument causes vvp to load the cadpli.vpl library module. This
|
||||||
|
activates the -cadpli= argument interpreter. The -cadpli=<module>:<boot_func>
|
||||||
|
argument, then, causes vvp, through the cadpli module, to load the loadable
|
||||||
|
PLI application, invoke the my_boot function to get a veriusertfs table, and
|
||||||
|
scan that table to register the system tasks and functions exported by that
|
||||||
|
object. The format of the -cadpli= extended argument is essentially the same
|
||||||
|
as the +loadpli1= argument to Verilog-XL.
|
||||||
|
|
||||||
|
The integration from this point is seamless. The PLI application hardly knows
|
||||||
|
that it is being invoked by Icarus Verilog instead of Verilog-XL, so operates
|
||||||
|
as it would otherwise.
|
||||||
|
|
||||||
|
Other References
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Since the above only explains how to get PLI/VPI working with Icarus Verilog,
|
||||||
|
here are some references to material to help with the common aspects of
|
||||||
|
PLI/VPI.
|
||||||
|
|
||||||
|
* Principles of Verilog PLI by Swapnajit Mittra. ISBN 0-7923-8477-6
|
||||||
|
* The Verilog PLI Handbook by Stuart Sutherland. ISBN 0-7923-8489-X
|
||||||
Loading…
Reference in New Issue