MyHDL supports co-simulation by a Cosimulation object.
A Cosimulation object must know how to run a HDL simulation.
Therefore, the first argument to its constructor is a command string
to execute a simulation.
The way to generate and run an simulation executable is simulator
dependent. For example, in Icarus Verilog, a simulation executable
for our example can be obtained obtained by running the
iverilog compiler as follows:
% iverilog -o bin2gray -Dwidth=4 bin2gray.v dut_bin2gray.v
This generates a bin2gray executable for a parameter width
of 4, by compiling the contributing verilog files.
The simulation itself is run by the vvp command:
% vvp -m ./myhdl.vpi bin2gray
This runs the bin2gray simulation, and specifies to use the
myhdl.vpi PLI module present in the current directory. (This is
just a command line usage example; actually simulating with the
myhdl.vpi module is only meaningful from a
Cosimulation object.)
We can use a Cosimulation object to provide a HDL
version of a design to the MyHDL simulator. Instead of a generator
function, we write a function that returns a Cosimulation
object. For our example and the Icarus Verilog simulator, this is done
as follows:
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)
After the executable command argument, the Cosimulation
constructor takes an arbitrary number of keyword arguments. Those
arguments make the link between MyHDL Signals and HDL nets, regs, or
signals, by named association. The keyword is the name of an argument
in a $to_myhdl or $from_myhdl call; the argument is
a MyHDL Signal.
With all this in place, we can now use the existing unit test
to verify the Verilog implementation. Note that we kept the
same name and parameters for the the bin2gray function:
all we need to do is to provide this alternative definition
to the existing unit test.
Let's try it on the Verilog design:
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}; // zero-extend input
always @(extB) begin
for (i=0; i < width; i=i+1)
G[i] <= extB[i+1] ^ extB[i];
end
endmodule
When we run our unit test, we get:
% python test_bin2gray.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
About this document