1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00
This commit is contained in:
jand 2003-05-12 23:24:41 +00:00
parent 3a7bdd972c
commit ab3a7f2e58

253
doc/cosimulation.tex Normal file
View File

@ -0,0 +1,253 @@
\chapter{MyHDL as a hardware verification language}
\section{Introduction}
One of the most exciting possibilities of \myhdl\
is to use it as a hardware verification language (HVL).
A HVL is a language used to write test benches and
verification environments, and to control simulations.
Nowadays, it is generally acknowledged that HVL's
should be equipped with modern software techniques,
such as object orientation. The reason is that verification
it the most complex and time-consuming task of the
design process: consequently every useful technique
is welcome. Moreover, test benches need not be
implementable; therefore there are no implementability
constraints on creativity.
Technically, verification of a design implemented in
another language requires cosimulation. \myhdl\ is
enabled for cosimulation with any HDL simulator that
has a procedural language interface (PLI). The \myhdl\
side is designed to be independent of a particular
simulator; however, for each HDL simulator a specific
PLI module will have to be written in C. Currently,
the \myhdl\ release contains a PLI module to interface
to the Icarus Verilog simulator. This interface will
be used in the examples in the present chapter.
\section{The HDL side}
To introduce cosimulation, we will continue to use the Gray encoder
example from the previous chapters where we have designed it and
written unit tests for it in \myhdl{}. Now suppose that we want to
synthesize it and write it in Verilog for that purpose. Clearly we would
like to reuse our unit test verification environment. This is exactly
what \myhdl\ offers.
To start, let's recall the Gray encoder written in \myhdl{}:
\begin{verbatim}
def bin2gray(B, G, width):
""" Gray encoder.
B -- input intbv signal, binary encoded
G -- output intbv signal, gray encoded
width -- bit width
"""
while 1:
yield B
for i in range(width):
G.next[i] = B[i+1] ^ B[i]
\end{verbatim}
To show the cosimulation flow, we don't need the Verilog
implementation yet, but only the interface. Our Gray encoder in
Verilog would have the following interface:
\begin{verbatim}
module bin2gray(B, G);
parameter width = 8;
input [width-1:0] B;
output [width-1:0] G;
....
\end{verbatim}
To write a test bench, one creates a new module that instantiates the
design under test (DUT). The test bench declares nets and
regs (or signals in VHDL) that are attached to the DUT, and to
stimulus generators and response checkers. In an all HDL flow, the
generators and checkers are written in the HDL itself, but we will
want to write them in \myhdl{}. To make the connection, we need to
declare which regs \& nets are driven and read by the \myhdl\
simulator. For our example, this is done as follows:
\begin{verbatim}
module dut_bin2gray;
reg [`width-1:0] B;
wire [`width-1:0] G;
initial begin
$from_myhdl(B);
$to_myhdl(G);
end
bin2gray dut (.B(B), .G(G));
defparam dut.width = `width;
endmodule
\end{verbatim}
The \code{\$from_myhdl} call declares which regs are driven by
\myhdl{}, and the \code{\$to_myhdl} call which regs \& nets are read
by it. These calls can have an arbitrary number of arguments. They
are defined in a PLI module written in C. They are made available to
the simulation in a simulator-dependent manner.' In Icarus Verilog,
the commands are defined in a \code{myhdl.vpi} module that is compiled
from C source code.
\section{The \myhdl\ side}
\myhdl\ supports cosimulation by a \code{Cosimulation} object.
A \code{Cosimulation} object must know how to run a HDL cosimulation.
Therefore, the first argument to its constructor is a command string
to run the simulator executable. The way to generate and run such an
executable is simulator dependent.
For example, in Icarus Verilog, a simulation executable for our
example can be obtained obtained by running the \code{iverilog}
compiler as follows:
\begin{verbatim}
% iverilog -o bin2gray -Dwidth=4 bin2gray.v dut_bin2gray.v
\end{verbatim}
This generates a \code{bin2gray} executable for a parameter \var{width}
of 4, by compiling the contributing verilog files.
The simulation itself is run by the \code{vvp} command:
\begin{verbatim}
% vvp -m ./myhdl.vpi bin2gray
\end{verbatim}
This runs the \code{bin2gray} simulation, and specifies to use the
\code{myhdl.vpi} PLI module present in the current directory. (This is
just an example of the command line usage of \code{vvp}; actually
simulating with the \code{myhdl.vpi} module is only meaningful from a
\code{Cosimulation} object.
We can use a \code{Cosimulation} object to provide a HDL simulation
version of a design to the \myhdl\ simulator. Instead of returning
generators, we return a \code{Cosimulation} object. For our example
and the Icarus Verilog simulator, this is done as follows:
\begin{verbatim}
import os
from myhdl import Cosimulation
cmd = "iverilog -o bin2gray -Dwidth=%s bin2gray.v dut_bin2gray.v"
def bin2gray(B, G, width):
os.system(cmd % width)
return Cosimulation("vvp -m ./myhdl.vpi bin2gray", B=B, G=G)
\end{verbatim}
After the executable command argument, the \code{Cosimulation}
constructor takes an arbitrary number of keyword arguments. Those
arguments make the links between \myhdl\ Signals and HDL nets, regs,
or signals. The keyword is the name of the argument in a
\code{\$to_myhdl} or \code{\$from_myhdl} call; the argument is the
\myhdl\ Signal.
With all this in place, we can now use the \emph{same} unit test
to verify Verilog implementations. Let's quickly try it just to be
sure:
\begin{verbatim}
module bin2gray(B, G);
parameter width = 8;
input [width-1:0] B;
output [width-1:0] G;
reg [width-1:0] G;
integer i;
always @(B) begin
for (i=0; i < width-1; i=i+1)
G[i] <= B[i+1] ^ B[i];
end
endmodule
\end{verbatim}
If we run our unit test we get:
\begin{verbatim}
% python test_bin2gray.py
Check that only one bit changes in successive codewords ... ERROR
Check that all codewords occur exactly once ... FAIL
Check that the code is an original Gray code ... ERROR
...
\end{verbatim}
Oops! It seems we still have a bug! Oh yes, but of course,
we need to zero-extend the input to get the msb output bit
correctly:
\begin{verbatim}
module bin2gray(B, G);
parameter width = 8;
input [width-1:0] B;
output [width-1:0] G;
reg [width-1:0] G;
integer i;
wire [width:0] extB;
assign extB = {1'b0, B};
always @(extB) begin
for (i=0; i < width; i=i+1)
G[i] <= extB[i+1] ^ extB[i];
end
endmodule
\end{verbatim}
And now:
\begin{verbatim}
% python test_all.py
Check that only one bit changes in successive codewords ... ok
Check that all codewords occur exactly once ... ok
Check that the code is an original Gray code ... ok
----------------------------------------------------------------------
Ran 3 tests in 2.729s
OK
\end{verbatim}
\section{Restrictions}
\section{Implementation notes}