Icarus Verilog: Open-Source Verilog More Than a Year Later
About 16 months ago, in the February 2001 Linux Journal [see www.linuxjournal.com/article/4428], we reviewed the state of open source in electronic design automation (EDA) with an interview that focused on Stephen Williams, the author of a leading open-source EDA project, the Icarus Verilog compiler [see page 80 of this issue for a new interview with Stephen Williams].
We can look back and forward to the benefits that open-source development methods bring to projects like Icarus Verilog. This article offers more technical details on design with Verilog, as well as explores some of the technical basis for the Icarus Verilog compiler. Also, at the end of this article, we list some excellent reference books on Verilog, as well as web site addresses where you can find information on numerous alternative open-source EDA projects.
Icarus Verilog is a command-line tool that compiles the source design, written in Verilog, to the target format. Normally, the target format is the input to the vvp simulation engine, but there are other target formats that can be selected at the command line.
The obvious first example is the ubiquitous “Hello, World.” program:
module test; initial $display("Hello, World."); endmodule
This compiles and executes trivially with the command sequence:
% iverilog -oa.vvp hello.v % vvp a.vvp Hello, WorldThe hardware engineer quickly wants to move on to more interesting examples that reflect the problems of hardware design. A simple example that tests a model for a counter is typical (see Listing 1). In both the hello.v and counter1.v examples, the compiler is given a source file that it compiles to a vvp-format output file, and the vvp program executes the generated file.
In Verilog programs, modules are the object types that are created by the designer to model a hardware device. Modules instantiate other modules and include code of their own to describe the device being modeled. The designer then instantiates root modules to represent the entire device being modeled.
Verilog compilers typically infer which modules in a design are root modules by noting in the programmer-supplied source which modules are not instantiated anywhere else. In the hello.v example, there was only the module “test”, which was made the root. In the counter1.v program, the module “counter” was instantiated by test, and only test is not otherwise instantiated, so test is the root.
With Icarus Verilog, programmers can either allow this heuristic to guess the root modules or can use -s flags to list root modules explicitly.
As programs get larger, programmers need the ability to create multifile programs and libraries. Libraries are also useful as vendor-supplied models for commercially available devices. Icarus Verilog supports automatic libraries in a portable manner.
An automatic library format is an industry standard. It is a directory of Verilog source files, each containing a module per file with the file named after the module that it contains. For example, counter.v contains the counter module. The location of the library is given to the Icarus Verilog compiler with the -y flag on the command line or in a command file.
Using automatic libraries, our counter1.v example can be broken into two parts: the library modules and the main program. In this example, it makes sense to move the counter module into lib/counter.v and keep the test module in our counter2.v program. See Listing 2 for how to use counter2.v in a two-part manner.
Icarus Verilog first tries to compile the counter2.v program. When it gets to the instantiation of the counter module, it notes that it does not have a counter module definition, searches the libraries it knows about (from -y flags) and finds the lib/counter.v file. It parses this new Verilog source, saves the module definitions it finds and continues to compile the original source. Library lookups recurse, so library modules may instantiate other library modules, with the compiler accumulating module definitions until the program is complete.
Icarus Verilog has the further convenience of supporting command files. Command files are text files that contain filenames, path declarations and other compilation directives. We can create for our counter2.v example a command file that looks like this:
counter2.txt: # this is a private library -y lib # project source files for this configuration counter2.v
And run the program like this:
% iverilog -c counter2.txt -o a.vvp % vvp a.vvpFor this small program the command file is not much use, but as designs get larger (hundreds of source files is not unusual) the command file becomes indispensable.
Icarus Verilog also includes a unique feature not available to other Verilog compilers: the loadable target API. This is a C API for loadable modules that the compiler can invoke to generate output in new formats. The vvp code generator is itself a loadable target module that is invoked when vvp simulation is requested (the default). There are also the null code generator and the fpga code generator.
The loadable target API is available to C programmers through the ivl_target.h header file included with and installed by Icarus Verilog packages. This API allows C programmers to write new output code generators for the Icarus Verilog compiler.
The vvp runtime also supports a subset of the standard Verilog VPI interface. This is a runtime C API that allows programmers to write new system tasks that the Verilog source can call. Existing examples of system tasks are the $stop and $monitor statements in the counter2.v example source file. All the standard core system tasks are written in Icarus Verilog using the VPI API.