Myhdl BlockError


#1

Hi,

Just started myhdl couples of days ago. It is amazing and I went through the documents and examples those days. After that I started to practice with my first sample code. To implement a simple fifo with myhdl on my own.

However problem arise and I can not solve it on my own even after refer back to the sample code many times. So would like to seek help here.

Ok, this is the source code I am working on.

fifo.py

from myhdl import *

@block
def fifo(clk,rst,wr,re,data,q,status):

wr_pt = Signal(modbv(0)[9:])
rd_pt = Signal(modbv(0)[9:])

full  = Signal(bool(0))
empty = Signal(bool(1))

mem = [Signal(intbv(0)[8:]) for i in range(256)]

#status[0] = full
#status[1] = empty

@always_comb
def status():
    full.next = (wr_pt - rd_pt == 256)
    empty.next = (wr_pt - rd_pt == 0)	


@always_seq(clk.posedge, reset=rst)
def write():
if(wr):
        if(not full):
            mem[wr_pt].next = data
            wr_pt.next = wr_pt + 1
        else:
            status[0].next = 1


@always_seq(clk.posedge,reset=rst)
def read():
    if(re):
        if(not empty):
        	q = mem[rd_pt]
        	rd_pt.next = rd_pt + 1
        else:
            status[1].next = 1

return status,read,write

@block
def bench():

clk = Signal(bool(0))
rst = ResetSignal(0, active=0, async=True)

wr = Signal(bool(0))
re = Signal(bool(0))
data = Signal(0)
q	= Signal(0)
status = Signal(0)

dut = fifo(clk,rst,wr,re,data,q,status)

HALF_PERIOD = delay(10)

@always(HALF_PERIOD)
def clockGen():
    clk.next = not clock

@block
def write(d):
    yield clock.negedge
    data.next = d
    wr.next = 1
    yield clock.negedge
    wr.next = 0

@instance
def stimulate():
    rst.next = 0
    for i in range(3):
        yield clk.negedge

    rst.next = 1
    write(0x44)

    yield clk.negedge
    raise StopSimulation()

return dut,clockGen,write,stimulate

def main():
tb = bench()
tb.run_sim()

if name == ‘main’:
main()

After run python3 fifo.py ( My working environment is ubuntu python3.5), I got the following message.

Traceback (most recent call last):
File “fifo.py”, line 92, in
main()
File “fifo.py”, line 88, in main
tb = bench()
File “/usr/local/lib/python2.7/dist-packages/myhdl-1.0.dev0-py2.7.egg/myhdl/_block.py”, line 125, in call
self.srcline, *args, **kwargs)
File “/usr/local/lib/python2.7/dist-packages/myhdl-1.0.dev0-py2.7.egg/myhdl/_block.py”, line 159, in init
self._verifySubs()
File “/usr/local/lib/python2.7/dist-packages/myhdl-1.0.dev0-py2.7.egg/myhdl/_block.py”, line 174, in _verifySubs
raise BlockError(_error.ArgType % (self.name,))
myhdl.BlockError: bench_1: A block should return block or instantiator objects


#2

I guess you intended to write an @instance instead of an @block to decorate the def write(d): in the test-bench?


#3

I do not quite understand the difference among those decorate. such as block, instance. Could you help me clarify the difference a little bit?

And if I change the write from block to instance. it report another error:

File “fifo.py”, line 64, in bench
@instance
File “/usr/local/lib/python3.5/dist-packages/myhdl-1.0.dev0-py3.5.egg/myhdl/_instance.py”, line 80, in instance
raise InstanceError(_error.NrOfArgs)
myhdl.InstanceError: decorated generator function should not have arguments


#4

I was a bit quick …
the def write(d): is just a simple function and should not have any decorator at all.


#5

ok, Thanks. This time at least the simulation run without problem. However it is not as expected.

I change the fifo.py test bench part to the follow.

fifo.py

from myhdl import *

@block
def fifo(clk,rst,wr,re,data,q,status):
… Does not changed

  return status,read,write

clk = Signal(bool(0))
rst = ResetSignal(0, active=0, async=True)

wr = Signal(bool(0))
re = Signal(bool(0))
data = Signal(0)
q = Signal(0)
status = Signal(0)

dut = fifo(clk,rst,wr,re,data,q,status)

def tb_write(d):

print("enter tb_write : d=%s" % d)
yield clk.negedge
data.next = d
wr.next = 1
yield clk.negedge
wr.next = 0

@block
def bench():

HALF_PERIOD = delay(10)

@always(HALF_PERIOD)
def clockGen():
    clk.next = not clk

@instance
def stimulate():
    rst.next = 0
    for i in range(3):
        yield clk.negedge

    rst.next = 1
    print("write to fifo")
    tb_write(0x44)
    print("write to fifo finished")
    

    yield clk.negedge
    for i in range(6):
        yield clk.negedge
    
    raise StopSimulation()

return clockGen,stimulate

Then I run it again. The simulation goes fine and vcd waveform also got dumped. as the log below shows.

$python3 fifo.py
write to fifo
write to fifo finished

but seems tb_write does not get executed at all. “enter tb_write : d = %s” %d" message do not got printed out. Why?


#6

Ok, managed to solve the problem myself. I used a generator for write which run parallel to stimulate. solved this issue. However still interest if it is possible to call a function or kind of block of code in instance decorator.


#7

You have to precede a call to a function with a yield: as in: yield tb_write(0x44)


#8

Thanks very much, It worked!