Exception raised on reset signal

I’m stalled trying to figure out the cause of this exception. I’ve tried following the FSM example in the user manual and I think it looks real close but that one runs and mine does not. Can anyone spot what I’ve done wrong?

from myhdl import *
from random import randrange


CLOCK = 40
HALF_CLOCK = delay(int(CLOCK / 2))


@block
def dffe(data_in, data_out, enable, clear, clock, reset):

	@always_seq(clock.posedge, reset=reset)
	def logic():
		if clear:
			data_out.next = 0
		elif enable:
			data_out.next = data_in

	return logic


@block
def test_dffe():

	clock = Signal(bool(0))
	reset = ResetSignal(0, active=1, async=True)
	clear = Signal(bool(0))
	enable = Signal(bool(0))

	data_in = Signal(intbv(0))
	data_out = Signal(intbv(0))

	inst = dffe(data_in, data_out, clock, reset, enable, clear)

	@always(HALF_CLOCK)
	def clock_generator():
		clock.next = not clock

	@instance
	def reset_generator():
		reset.next = True
		yield delay(100)
		reset.next = False
		while True:
			yield delay(1000)

	@instance
	def stimulus():
		yield delay(150)
		enable.next = True

		for _ in range(10):
			yield delay(randrange(50, 100))
			data_in.next = randrange(0, 255)

		yield delay(1000)
		enable.next = False

		yield delay(100)
		clear.next = True
		yield delay(CLOCK)
		clear.next = False

		raise StopSimulation()

	return inst, clock_generator, reset_generator, stimulus


def simulate():
	tb = test_dffe()
	tb.config_sim(trace=True)
	tb.run_sim()


def convert(hdl):
	clock = Signal(bool(0))
	reset = ResetSignal(0, active=1, async=True)
	clear = Signal(bool(0))
	enable = Signal(bool(0))
	data_in = Signal(intbv(0))
	data_out = Signal(intbv(0))

	inst = dffe(data_in, data_out, clock, reset, clear, enable)
	inst.convert(hdl)


if __name__ == '__main__':
	simulate()
	# convert(hdl='Verilog')

When I run this, I get this.

C:\MyPython\timing_engine\venv\Scripts\python.exe C:/MyPython/timing_engine/dffe.py
Traceback (most recent call last):
  File "C:/MyPython/timing_engine/dffe.py", line 88, in <module>
	simulate()
  File "C:/MyPython/timing_engine/dffe.py", line 70, in simulate
	tb = test_dffe()
  File "C:\MyPython\timing_engine\venv\lib\site-packages\myhdl\_block.py", line 196, in __call__
	self.srcline, *args, **kwargs)
  File "C:\MyPython\timing_engine\venv\lib\site-packages\myhdl\_block.py", line 218, in __init__
	self.subs = _flatten(func(*args, **kwargs))
  File "C:/MyPython/timing_engine/dffe.py", line 33, in test_dffe
	inst = dffe(data_in, data_out, clock, reset, enable, clear)
  File "C:\MyPython\timing_engine\venv\lib\site-packages\myhdl\_block.py", line 196, in __call__
	self.srcline, *args, **kwargs)
  File "C:\MyPython\timing_engine\venv\lib\site-packages\myhdl\_block.py", line 218, in __init__
	self.subs = _flatten(func(*args, **kwargs))
  File "C:/MyPython/timing_engine/dffe.py", line 12, in dffe
	@always_seq(clock.posedge, reset=reset)
  File "C:\MyPython\timing_engine\venv\lib\site-packages\myhdl\_always_seq.py", line 69, in always_seq
	raise AlwaysSeqError(_error.ResetType)
myhdl.AlwaysError: reset argument should be a ResetSignal

Process finished with exit code 1

Your dffe block has arguments in order data_in, data_out, enable, clear, clock, reset, whereas the instantiation in test_dffe has them in order data_in, data_out, clock, reset, enable, clear, and convert in a yet another permutation data_in, data_out, clock, reset, clear, enable.

Ugh! How embarrassing. What is the generally-accepted coding style for this? Is anyone using named parameters?

Many thanks for your kind help.

I was just called out on alternative coding style, so I can’t really say. :smile: However, I usually put the clock and reset first, since all blocks have them.

@mhavu alternative doesn’t necessarily mean bad :slight_smile: I was just surprised by your use of instantiating a new intbv() on every rising clock edge.

Putting any required parameters (if any) first, then clock and reset, followed by the mandatory inputs, then the always generated outputs and finally the optionals is what I do, e.g.:

def Counter( WIDTH_COUNT, Clk, Reset, SClr, CntEn, Q, IsMax=None, WRAP_AROUND=False):
    '''a simple counter '''
    ....

Using named parameters is certainly a possibility (and the preferred way in VHDL) but once you make up your own coding rules and stick to them, you won’t get surprised that often.

On My side, I use classes and put the configuration parameters in class parameters :

class Counter( ) :
    '''a simple counter '''
    def __init__(self, WIDTH_COUNT, IsMax=None, WRAP_AROUND=False):
        pass

    def hdl(self,  Clk, Reset, SClr, CntEn, Q) :
        pass

I use classes differently:

class Counter(object):
    '''a simple counter '''
    def __init__(self, WIDTH_COUNT, Clk, Reset, CntEn=None, Q=None):
        self.WIDTH_COUNT= WIDTH_COUNT
        self.Clk = Clk
        self.Reset = Reset
        self.CntEn = CntEn if CntEn is not None else Signal(bool(1))
        self.Q = Q if Q is not None else Signal(modbv(0)[WIDTH_COUNT:])

    @block
    def rtl(self):
        ''' the logic '''
        @always_seq(self.Clk.posedge, reset=self.Reset)
        def counter():
            if self.CntEn:
                self.Q.next = self.Q + 1

        return counter