Verilog, as a language designed for verifying logic allows to describe a hardware setup in a very general way. Simulators, such as Icarus Verilog can then be used to simulate this hardware setup. Tools such as gtkwave can be used to verify the output of a circuit by looking at the waveforms the simulation generates.
Simulavr comes with an interface to (Icarus) Verilog. If the configure script finds the necessary header file for the interface, the so called VPI (Verilog Procedural Interface) to Icarus Verilog will be build. The result of this is a file called avr.vpi. This file, in essence a shared library, can then be used as an externally loaded module after compilation:
$ iverilog [...] # compile verilog .v into .vvp $ vvp -M<path-to-avr.vpi> -mavr [...] # run compiled verilog # with additional # avr.vpi module
In principle, it would also be possible to implement the AVR completely in verilog (and there are several existing models, see e.g. opencores.org), but this would result in decreased performance and duplicated effort, as not only the core needs to be implemented, but also the complex on-board periphery.
The Verilog interface comes with glue code on the verilog side, for
which the main file is avr.v in src/verilog. This is a
thin wrapper in Verilog around the exported methods from the core of
Simulavr, consisting of the AVRCORE
module encapsulating one
AVR core and avr_pin
for I/O through any AVR pin. On top of
this, files named avr_*.v exist in the same directory which
contain verilog modules reflecting particular AVR models from
Simulavr. The modules in these files are meant to be the interface to
be used to connect to simulavr by the user, they have a very simple signature:
module AVRxyz(CLK, port1, port2, ...);
where port1
, port2
, ... are simple arrays of
inout
wires representing the various ports of the selected
AVR. Note that the width of the arrays as visible from the Verilog
side is always eight; this does not mean that all bits are connected
on the simulavr side!
Clock generation and distribution to the AVR cores is done from the verilog side. Simply connect a clock source with the preferred frequency to the CLK input of the AVR code.
The more complete, low level interface to simulavr in avr.vpi can be accessed directly. For documentation of the available functions, see either src/vpi.cpp or look into the implementation of the high level modules in avr_*.v.
A simple run with the avr.vpi interface could look like this:
$ iverilog -s test -v -I. $(AVRS)/avr.v $(AVRS)/avr_ATtiny15.v \ $(AVRS)/avr_ATtiny2313.v -o test.vvp
Here for a model having both an ATtiny15 and an ATtiny2313 in the
simulation, and the top module test
and the environment
variable $AVRS pointing to the right directory.
A set of a few simple examples has been put into the verilog/examples subdirectory of the Simulavr source distribution. This directory also contains a Makefile which can be used as an example of command sequences for compiling verilog, running it and producing .vcd output files to be viewed with gtkwave.