Skip to content

Instantly share code, notes, and snippets.

@j-marjanovic
Last active January 3, 2023 00:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j-marjanovic/1cd36b9da44280e890b6 to your computer and use it in GitHub Desktop.
Save j-marjanovic/1cd36b9da44280e890b6 to your computer and use it in GitHub Desktop.
Simple example of MyHDL and Verilog co-simulation

Introduction

This code snippet demonstrates a co-simulation of Verilog code and MyHDL code. The three modules here presents the absolute minimum for a co-simulation.

The counter_top.v is the top level module. It instantiates the counter module (found in file counter.v), which is the module we would like to evaluate. Also instantiated are the signals which are feed from and to MyHDL.

The hierarchy is shown on the following scheme:

                           +-------------+
                           |             |
                           | counter_top |
                           |             |
                           +-------------+
                             /         \
                            /           \
                           /             \
                          /               \
                         /                 \
                        V                   V
    +-------------------------+      +----------------+
    |    counter_test.py      |      |                |
    |-------------------------|      |  counter (DUT) |
    | +------------+          |      |                |
    | | clk_driver |          |      +----------------+
    | +------------+          |
    |                         |
    |          +-----------+  |
    |          | checker   |  |
    |          +-----------+  |
    +-------------------------+

The MyHDL program creates instances of clk_driver, counter and a checker. The clk_driver and checker are MyHDL modules, while counter is the Cosimulation object, which enables the simulation of Verilog modules.

Usage

Run the counter_test.py script (the myhdl.vpi should be placed in the same directory) with the following command:

python3 counter_test.py

The successful simulation creates counter_top.vcd, which can be viewed with GTKWave:

gtkwave counter_top.vcd
// Jan Marjanovic, 2015
//
// This is a Verilog module which will be used as DUT in MyHDL-Verilog
// co-simulation example
module counter (
input clk,
output [3:0] q
);
reg [3:0] cntr = 0;
assign q = cntr;
always @ (posedge clk) begin
$display("from counter module, t=%5d, q=%d", $time, cntr);
cntr <= cntr + 1;
end
endmodule
#!/usr/bin/env python3
'''
Jan Marjanovic, 2015
A extremely simple example of co-simulation of MyHDL and Verilog code.
'''
import os
from myhdl import Cosimulation, Simulation, Signal, delay, always, intbv, now
def clk_driver(clk, period=10):
''' Clock driver '''
@always(delay(period//2))
def driver():
clk.next = not clk
return driver
def counter(clk, q):
''' A Cosimulation object, used to simulate Verilog modules '''
os.system('iverilog -o counter counter.v counter_top.v')
return Cosimulation('vvp -m ./myhdl.vpi counter', clk=clk, q=q)
def checker(clk, q):
''' Checker which prints the value of counter at posedge '''
@always(clk.posedge)
def check():
print('from checker, time=', now(), ' q=', q)
return check
clk = Signal(0)
q = Signal(intbv(0)[4:])
clk_driver_inst = clk_driver(clk)
counter_inst = counter(clk, q)
checker_inst = checker(clk, q)
sim = Simulation(clk_driver_inst, counter_inst, checker_inst)
sim.run(200)
// Jan Marjanovic, 2015
//
// This is a top module which combines DUT and MyHDL signals
module counter_top;
reg clk = 0;
wire [3:0] q;
counter dut (.clk(clk), .q(q));
initial begin
$from_myhdl(clk);
$to_myhdl(q);
end
initial begin
$dumpfile("counter_top.vcd");
$dumpvars();
end
endmodule
@bat52
Copy link

bat52 commented Dec 30, 2022

Thank you for the example!
That works, even though now myHDL requires the use of @block decorators before the module instances.
Yet, in my case the .vcd file is empty and gtkwave ends immediately with message:
"No symbols in VCD file..is it malformed? Exiting!"
Have you experienced anything like that ?

@j-marjanovic
Copy link
Author

Uhh, sorry, this code is from 2015, haven't touched MyHDL in the last couple of years.

Maybe try adding some $displays to see what gets executed and what not?

@bat52
Copy link

bat52 commented Jan 3, 2023

Thank you, I have solved this: your code is fine, and the .vcd too. I was launching gtkwave as
os.system('gtkwave dunp.vcd')
and using instead
os.system('gtkwave dunp.vcd &')
made it work, even though I have no clear explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment