Cosimulation output port conflict (X)

Hello,

I have a very simple blink module as follows:

@block
def Blink(clk:SignalType, rst:ResetSignal, blink, enable, period):

	count = Signal(modbv(0)[20:])

	@always(clk.posedge)
	def logic():
		if enable:
			if count == period:
				count.next = 0
				blink.next = not blink
			else:
				count.next = count + 1
		if rst:
			count.next = 0

	return logic

And I am trying to cosimulate it with icarus verilog on windows. I would like to convert the myhdl description and then run the cosimulation on it as part of the same testcase as follows:

from blink import *

@block
def test(cosim=False):

	clk = Signal(bool(0))
	rst = Signal(bool(1))

	io_enable = Signal(bool(0))
	io_blink  = Signal(bool(0))

	# creating the dut
	dut = Blink(clk, rst, io_blink, io_enable, 100)

	# always converting in order to catch possible errors
	dut.convert(hdl='Verilog', trace=True)

	sources = [
		"Blink.v",
		"tb_Blink.v"]

	if cosim:
		cmd = ' '.join(["iverilog", '-o', 'test.o'] + sources)
		if(os.system(cmd) == 0):
			dut = Cosimulation("vvp -m ./myhdl test.o", clk=clk, rst=rst, enable=io_enable, blink=io_blink)

	# clock generation
	@always(delay(10))
	def clkgen():
		clk.next = not clk

	# stimulus generation
	@instance
	def stimulus():
		yield clk.posedge
		rst.next = 0
		io_enable.next = 1

		for i in range(1000):
			yield clk.posedge

		raise StopSimulation

	return clkgen, dut, stimulus

#########################################################

import os
import glob
import subprocess

def run(cosim=False, gui=False):
	os.chdir(get_abs_path("../sim"))

	clean()

	trace = True
	if cosim:
		trace = False

	i = test(cosim)
	i.config_sim(trace=trace, tracebackup=False)
	i.run_sim(quiet=1)

	if gui:
		subprocess.run(["gtkwave", "*.vcd"])


def clean():
	os.chdir(get_abs_path("../sim"))

	# List of extensions you want to delete
	extensions = ['*.vcd', '*.v', '*.o']

	# Loop through each extension and delete matching files
	for ext in extensions:
		for file_path in glob.glob(ext):
			if os.path.isfile(file_path):
				os.remove(file_path)
				print(f"Deleted: {file_path}")


if __name__ == "__main__":
	run(cosim=True, gui=True)

The simulation runs fine but my io_blink signal is in conflicted state, like both the verilog and the testcase were trying to drive it at the same time. Any idea what I might be doing wrong?

Allright I will reply to myself. Of course the root cause was a rookie mistake in my “blink” implementation, because I wasn’t resetting the blink output port. The problem however is that in GTKWAVE I see the signal as “X” (multiple drivers) while usually one would expect a “U” (undefined) in this situation, which was cause of confusion.

I wonder if this has to do with GTKWAVE or with Icarus Verilog, anyway, it all works ok for the rest.

You can write blink as:

@block
def Blink(clk:SignalType, rst:ResetSignal, blink, enable, period):

	count = Signal(modbv(0)[20:])

	@always_seq(clk.posedge, reset=rst)
	def logic():
		if enable:
			if count == period:
				count.next = 0
				blink.next = not blink
			else:
				count.next = count + 1


	return logic

and declare rst = ResetSignal(0,1, isasync=False) in stead of rst = Signal(bool(1))

All outputs in the `logic()’ section will be nicely reset (to their initial value)