5.3 The MyHDL side

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