MyHDL – Notes, Exercises, and Questions on the User Manual

2.1 A basic MyHDL simulation

def sayHello():

    while True:          ###1

        yield delay(10)

        print "%s Hello World!" % now()

The yield statement in MyHDL has a similar meaning as the wait statement in VHDL: the statement suspends execution of a generator, and its clauses specify the conditions on which the generator should wait before resuming. In this case, it should wait for a delay.

Q1:  How does Python know how to schedule delays, etc.?

A1:  The scheduling has nothing to do with Python.  All the yield statement does is return a specified object (or objects) and suspend the current function.  In this case, the object returned is a delay object constructed from class delay, which was imported from package myhdl.  Other parts of MyHDL know what to do with this object.

2.4 Bit Indexing

By convention, the lsb of an intbv object has index 0. ###Q1

Q1:  Why is the bit indexing backward?  How do we access a slice of an intbv object?

A1:  The bit positions are reversed compared to a normal Python string.  This makes the value of bit n simply 2**n independent of the length of the bit string, which is a much bigger plus than the negative of changing the left-to-right convention on the index notation.  intbv objects are not strings, they are simply displayed that way by the bin function to make them look like binary numbers.

>>> x = '1010'  # this is a Python string

>>> y = intbv(10)  # this is not

>>> x[0:3]

'101'

>>> y[4:1]

intbv(5L)

>>> bin(y[4:1])

'101'

>>>

To see how this works look at the _intbv module in <python-dir>/Lib/site-packages/myhdl/

Note:  __getslice__ has been deprecated since Python 2.0, but it would require a re-write of the __getitem__ function to make it support both simple indices and slices.

Ex1:  Find the functions that implement indexing and the XOR operator for objects of class intbv.  Confirm that these are the functions called when you evaluate an expression like B[i+1] ^ B[i].  Hint: Add print statements to these two functions.

Soln1:  First, we must find the module that intbv came from.  Assuming we can't remember which Python trick provides this wonderful "introspection" capability, let's start by just running the example from this section.  That will give us a live intbv object we can dissect in the interpreter.

>>> intbv

<class 'myhdl._intbv.intbv'>

Wow!  That was quick. intbv is a class found in module myhdl._intbv.  Let's import that module, and see where it comes from:

>>> import myhdl._intbv

>>> myhdl._intbv

<module 'myhdl._intbv' from 'C:\Python24\lib\site-packages\myhdl\_intbv.py'>

Read that file, and you will find functions __getitem__ and __xor__ which "intercept" the operators [ ] and ^ for items of class intbv.  These are the ones we need to modify.  Make sure you backup and restore the original _intbv.py file after you are done.  :>)

>>> B = intbv(6)

>>> B[2]

Hello from __getitem__, i = 2

intbv(1)

>>> B[2] ^ B[1]

Hello from __getitem__, i = 2

Hello from __getitem__, i = 1

Hello from __xor__

intbv(0)

>>>

3.2.1 Combinatorial Logic

Ex1:  Make a Python module from the example code in section 3.2.1.2 and verify that it runs correctly.  Then comment out the always_comb() statement and replace it with the equivalent sequence of simple Python statements.  Verify that it produces the same output.

Soln1:

##    return always_comb(muxlogic)

    while True:

        muxlogic()

        yield a, b, sel