Provided by: myhdl-doc_0.11-1_all bug

NAME

       myhdl - MyHDL Documentation Back to the main site »

THE MYHDL MANUAL

   Overview
       The  goal  of  the MyHDL project is to empower hardware designers with the elegance and simplicity of the
       Python language.

       MyHDL is a free, open-source package  for  using  Python  as  a  hardware  description  and  verification
       language.  Python  is  a very high level language, and hardware designers can use its full power to model
       and simulate their designs.  Moreover, MyHDL can convert a design to Verilog or  VHDL.  This  provides  a
       path into a traditional design flow.

       Modeling

       Python's  power  and  clarity make MyHDL an ideal solution for high level modeling.  Python is famous for
       enabling elegant solutions to complex modeling problems.   Moreover,  Python  is  outstanding  for  rapid
       application development and experimentation.

       The  key  idea behind MyHDL is the use of Python generators to model hardware concurrency. Generators are
       best described as resumable functions.  MyHDL generators are similar to  always  blocks  in  Verilog  and
       processes in VHDL.

       A hardware module (called a block in MyHDL terminology) is modeled as a function that returns generators.
       This  approach  makes  it  straightforward  to  support  features such as arbitrary hierarchy, named port
       association, arrays of instances, and conditional instantiation.   Furthermore,  MyHDL  provides  classes
       that  implement  traditional  hardware  description  concepts.  It  provides  a  signal  class to support
       communication between generators, a class to support bit oriented operations, and a class for enumeration
       types.

       Simulation and Verification

       The built-in simulator runs on top of the Python interpreter. It supports  waveform  viewing  by  tracing
       signal changes in a VCD file.

       With  MyHDL,  the Python unit test framework can be used on hardware designs.  Although unit testing is a
       popular modern software verification technique, it is still uncommon in the hardware design world.

       MyHDL can also be used as hardware verification language  for  Verilog  designs,  by  co-simulation  with
       traditional HDL simulators.

       Conversion to Verilog and VHDL

       Subject  to  some  limitations,  MyHDL designs can be converted to Verilog or VHDL.  This provides a path
       into a traditional design flow, including  synthesis  and  implementation.   The  convertible  subset  is
       restricted, but much wider than the standard synthesis subset.  It includes features that can be used for
       high level modeling and test benches.

       The  converter works on an instantiated design that has been fully elaborated. Consequently, the original
       design structure can be arbitrarily complex. Moreover, the conversion  limitations  apply  only  to  code
       inside   generators.   Outside   generators,  Python's  full  power  can  be  used  without  compromising
       convertibility.

       Finally, the converter automates a number of tasks that are hard in Verilog or VHDL directly.  A  notable
       feature is the automated handling of signed arithmetic issues.

   Background information
   Prerequisites
       You  need  a  basic understanding of Python to use MyHDL. If you don't know Python, don't worry: it is is
       one of the easiest programming languages to learn   [1].   Learning  Python  is  one  of  the  best  time
       investments that engineering professionals can make  [2].

       For  starters,  http://docs.python.org/tutorial  is probably the best choice for an on-line tutorial. For
       alternatives, see http://wiki.python.org/moin/BeginnersGuide.

       A working knowledge of a hardware description language such as Verilog or VHDL is helpful.

       Code examples in this manual are sometimes shortened for clarity. Complete  executable  examples  can  be
       found in the distribution directory at example/manual/.

   A small tutorial on generators
       Generators  were  introduced  in  Python  2.2.  Because  generators are the key concept in MyHDL, a small
       tutorial is included here.

       Consider the following nonsensical function:

          def function():
              for i in range(5):
                  return i

       You can see why it doesn't make a lot of sense. As soon as the  first  loop  iteration  is  entered,  the
       function returns:

          >>> function()
          0

       Returning is fatal for the function call. Further loop iterations never get a chance, and nothing is left
       over from the function call when it returns.

       To change the function into a generator function, we replace return with yield:

          def generator():
              for i in range(5):
                  yield i

       Now we get:

          >>> generator()
          <generator object at 0x815d5a8>

       When  a  generator  function  is  called,  it returns a generator object. A generator object supports the
       iterator protocol, which is an expensive way of saying that you can let it generate subsequent values  by
       calling its next method:

          >>> g = generator()
          >>> g.next()
          0
          >>> g.next()
          1
          >>> g.next()
          2
          >>> g.next()
          3
          >>> g.next()
          4
          >>> g.next()
          Traceback (most recent call last):
            File "<stdin>", line 1, in ?
          StopIteration

       Now  we  can  generate  the subsequent values from the for loop on demand, until they are exhausted. What
       happens is that the yield statement is like  a  return,  except  that  it  is  non-fatal:  the  generator
       remembers  its  state  and the point in the code when it yielded. A higher order agent can decide when to
       get the next value by calling  the  generator's  next  method.  We  say  that  generators  are  resumable
       functions.

       If  you are familiar with hardware description languages, this may ring a bell.  In hardware simulations,
       there is also a higher order agent, the Simulator, that interacts with such resumable functions; they are
       called  processes in VHDL and  always blocks in Verilog.  Similarly, Python generators provide an elegant
       and efficient method to model concurrency, without having to resort to some form of threading.

       The use of generators to model concurrency is the first key concept in MyHDL.  The second key concept  is
       a  related  one:  in  MyHDL, the yielded values are used to specify the conditions on which the generator
       should wait before resuming. In other words, yield statements work as general  sensitivity lists.

   About decorators
       Python 2.4 introduced a feature called decorators. MyHDL takes advantage of this feature  by  defining  a
       number  of  decorators that facilitate hardware descriptions. However, some users may not yet be familiar
       with decorators.  Therefore, an introduction is included here.

       A decorator consists of special syntax in front of a function  declaration.  It  refers  to  a  decorator
       function.  The decorator function automatically transforms the declared function into some other callable
       object.

       A decorator function deco is used in a decorator statement as follows:

          @deco
          def func(arg1, arg2, ...):
              <body>

       This code is equivalent to the following:

          def func(arg1, arg2, ...):
              <body>
          func = deco(func)

       Note that the decorator statement goes directly in front  of  the  function  declaration,  and  that  the
       function name func is automatically reused for the final result.

       MyHDL  uses  decorators  to  create  ready-to-simulate  generators from local function definitions. Their
       functionality and usage will be described extensively in this manual.

FOOTNOTES

       [1]  You must be bored by such claims, but in Python's case it's true.

       [2]  I am not biased.

   Introduction to MyHDL
   A basic MyHDL simulation
       We will introduce MyHDL with a classic Hello World style example. All example code can be  found  in  the
       distribution  directory under example/manual/.  Here are the contents of a MyHDL simulation script called
       hello1.py:

       When we run this simulation, we get the following output:

       The first line of the script imports a number of objects from the myhdl package. In Python  we  can  only
       use identifiers that are literally defined in the source file.

       Then,  we  define  a  function  called  HelloWorld.  In MyHDL, a hardware module is modeled by a function
       decorated with the block decorator. The name block was chosen to avoid confusion with the Python  concept
       of a module. We will use this terminology further on.

       The  parameter  list of the HelloWorld function is used to define the interface of the hardware block. In
       this first example, the interface is empty.

       Inside the top level function we declare a local function  called  say_hello  that  defines  the  desired
       behavior.  This  function is decorated with an always decorator that has a delay object as its parameter.
       The meaning is that the function will be executed whenever the specified delay interval has expired.

       Behind the curtains, the always decorator creates a Python generator and reuses the name of the decorated
       function for it. Generators are the fundamental objects in MyHDL, and we will say much  more  about  them
       further on.

       Finally,  the  top level function returns the say_hello generator. This is the simplest case of the basic
       MyHDL code pattern to define the contents of a hardware block. We will describe the general case  further
       on.

       In  MyHDL,  we  create  an  instance of a hardware block by calling the corresponding function. The block
       decorator make sure that the return value is actually an instance of a block class, with a useful API. In
       the example, variable inst refers to a HelloWorld block instance.

       To simulate the instance, we use its run_sim method. We can use it to run the simulation for the  desired
       amount of timesteps.

   Signals and concurrency
       An  actual  hardware  design  is  typically  massively  concurrent,  which  means  that a large amount of
       functional units are running in parallel. MyHDL supports this behavior by allowing an arbitrary number of
       concurrently running generators.

       With concurrency comes the problem of deterministic communication. Hardware languages use special objects
       to support deterministic communication between concurrent code. In particular, MyHDL  has a Signal object
       which is roughly modeled after VHDL signals.

       We will demonstrate signals and concurrency by extending and modifying our first  example.  We  define  a
       hardware block that contains two generators, one that drives a clock signal, and one that is sensitive to
       a positive edge on a clock signal:

       The  clock  driver  function clk_driver drives the clock signal. If defines a generator that continuously
       toggles a clock signal after a certain delay. A new value of a signal is specified by  assigning  to  its
       next attribute. This is the MyHDL equivalent of  the VHDL signal assignment and the  Verilog non-blocking
       assignment.

       The  say_hello  function is modified from the first example. It is made sensitive to a rising edge of the
       clock signal, specified by the posedge attribute of a signal. The edge specifier is the argument  of  the
       always decorator. As a result, the decorated function will be executed on every rising clock edge.

       The clk signal is constructed with an initial value 0. One generator drives it, the other is sensitive to
       it.  The  result of this communication is that the generators run in parallel, but that their actions are
       coordinated by the clock signal.

       When we run the simulation, we get:

   Parameters, ports and hierarchy
       We have seen that MyHDL uses functions to model hardware blocks. So far  these  functions  did  not  have
       parameters.  However,  to  create  general, reusable blocks we will need parameters.  For example, we can
       create a clock driver block as follows:

       The block encapsulates a clock driver generator. It has two parameters.

       The first parameter is clk is the clock signal. A asignal parameter  is MyHDL's way to model a dfn:port:.
       The second parameter is the clock period, with a default value of 20.

       As the low time of the clock may differ from the high time in case of an odd period, we  cannot  use  the
       always  decorator  with  a single delay value anymore. Instead, the drive_clk function is now a generator
       function with an explicit definition  of  the  desired  behavior.  It  is  decorated  with  the  instance
       decorator.  You can see that drive_clk is a generator function because it contains yield statements.

       When  a  generator function is called, it returns a generator object. This is basically what the instance
       decorator does. It is less sophisticated than the always decorator, but  it  can  be  used  to  create  a
       generator from any local generator function.

       The yield statement is a general Python construct, but MyHDL uses it in a specific way.  It 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,  the  generator
       waits for a certain delay.

       Note that to make sure that the generator runs "forever", we wrap its behavior in a while True loop.

       Similarly, we can define a general Hello function as follows:

       We can create any number of instances by calling the functions with the appropriate parameters. Hierarchy
       can be modeled by defining the instances in a higher-level function, and returning them. This pattern can
       be  repeated  for  an  arbitrary number of hierarchical levels. Consequently, the general definition of a
       MyHDL instance is recursive: an instance is either a sequence of instances, or a generator.

       As an example, we will create a higher-level function with four instances of the  lower-level  functions,
       and simulate it:

       As  in standard Python, positional or named parameter association can be used in instantiations, or a mix
       of both [1]. All these styles are demonstrated in the example above. Named association can be very useful
       if there are a lot of parameters, as the argument order in the call does not matter in that case.

       The simulation produces the following output:

   Terminology review
       Some commonly used terminology has different meanings in  Python  versus  hardware  design.  For  a  good
       understanding, it is important to make these differences explicit.

       A  module  in  Python  refers  to  all  source code in a particular file. A module can be reused by other
       modules by importing it. In hardware design on the other hand, a module typically refers  to  a  reusable
       unit  of hardware with a well defined interface. Because these meanings are so different, the terminology
       chosen for a hardware module in MyHDL is block instead, as explained earlier in this chapter.

       A hardware block can can be reused in  another block by instantiating it.

       An instance in Python (and other object-oriented languages) refers to  the  object  created  by  a  class
       constructor.  In hardware design, an instance is a particular incarnation of a hardware block, created by
       instantiating the block.  In MyHDL, such as block instance is actually an instance of a particular class.
       Therefore, the two meanings are not exactly the same, but they coincide nicely.

       Normally, the meaning the words "block" and "instance" should be clear from the  context.  Sometimes,  we
       qualify them with the words "hardware" or "MyHDL" for clarity.

   Some remarks on MyHDL and Python
       To conclude this introductory chapter, it is useful to stress that MyHDL is not a language in itself. The
       underlying  language  is Python,  and MyHDL is implemented as a Python package called myhdl. Moreover, it
       is a design goal to keep the myhdl package as minimalistic as possible, so that  MyHDL  descriptions  are
       very much "pure Python".

       To have Python as the underlying language is significant in several ways:

       • Python  is  a  very  powerful  high  level language. This translates into high productivity and elegant
         solutions to complex problems.

       • Python is continuously improved by some very clever minds, supported  by  a  large  user  base.  Python
         profits fully from the open source development model.

       • Python  comes with an extensive standard library. Some functionality is likely to be of direct interest
         to MyHDL users: examples include string handling, regular expressions, random number  generation,  unit
         test  support,  operating  system  interfacing  and GUI development. In addition, there are modules for
         mathematics, database connections, networking programming, internet data handling, and so on.

   Summary and perspective
       Here is an overview of what we have learned in this chapter:

       • Generators are the basic building blocks of MyHDL  models.  They  provide  the  way  to  model  massive
         concurrency and sensitivity lists.

       • MyHDL  provides decorators that create useful generators from local functions and a decorator to create
         hardware blocks.

       • Hardware structure and  hierarchy  is  described  with  Python  functions,  decorated  with  the  block
         decorator.

       • Signal objects are used to communicate between concurrent generators.

       • A block instance provides a method to simulate it.

       These concepts are sufficient to start modeling and simulating with MyHDL.

       However,  there  is  much  more  to  MyHDL. Here is an overview of what can be learned from the following
       chapters:

       • MyHDL supports hardware-oriented types that make it easier to write typical hardware models. These  are
         described in Chapter hwtypes.

       • MyHDL supports sophisticated and high level modeling techniques. This is described in Chapter model-hl.

       • MyHDL  enables  the  use  of modern software verification techniques, such as unit testing, on hardware
         designs. This is the topic of Chapter unittest.

       • It is possible to co-simulate MyHDL models with other HDL languages such as Verilog and VHDL.  This  is
         described in Chapter cosim.

       • Last  but  not  least,  MyHDL models can be converted to Verilog or VHDL, providing a path to a silicon
         implementation. This is the topic of Chapter conv.

FOOTNOTES

       [1]  All positional parameters have to go before any named parameter.

   Hardware-oriented types
   The intbv class
       Hardware design involves dealing with bits and bit-oriented operations. The standard Python type int  has
       most of the desired features, but lacks support for indexing and slicing. For this reason, MyHDL provides
       the intbv class. The name was chosen to suggest an integer with bit vector flavor.

       intbv  works  transparently  with  other  integer-like  types.  Like class int, it provides access to the
       underlying two's complement representation for bitwise operations. However, unlike int, it is  a  mutable
       type.  This means that its value can be changed after object creation, through methods and operators such
       as slice assignment.

       intbv supports the same operators as int for arithmetic. In addition, it provides a number of features to
       make it suitable for hardware design. First, the range of allowed values can be constrained.  This  makes
       it  possible to check the value at run time during simulation. Moreover, back end tools can determine the
       smallest possible bit width for representing the object.  Secondly, it supports bit level  operations  by
       providing an indexing and slicing interface.

       intbv objects are constructed in general as follows:

          intbv([val=None] [, min=None]  [, max=None])

       val  is  the  initial  value.  min  and  max  can  be  used  to constrain the value. Following the Python
       conventions, min is inclusive, and max is exclusive. Therefore, the allowed value range is min .. max-1.

       Let's look at some examples. An unconstrained intbv object is created as follows:

          >>> a = intbv(24)

       After object creation, min and max are available as attributes for inspection. Also, the standard  Python
       function len can be used to determine the bit width. If we inspect the previously created object, we get:

          >>> a
          intbv(24)
          >>> print(a.min)
          None
          >>> print(a.max)
          None
          >>> len(a)
          0

       As the instantiation was unconstrained, the min and max attributes are undefined. Likewise, the bit width
       is undefined, which is indicated by a return value 0.

       A constrained intbv object is created as follows:

       >>> a = intbv(24, min=0, max=25)

       Inspecting the object now gives:

          >>> a
          intbv(24)
          >>> a.min
          0
          >>> a.max
          25
          >>> len(a)
          5

       We see that the allowed value range is 0 .. 24,  and that 5 bits are required to represent the object.

       The  min  and  max bound attributes enable fine-grained control and error checking of the value range. In
       particular, the bound values do not have to be symmetric or powers of 2. In all cases, the bit  width  is
       set appropriately to represent the values in the range. For example:

          >>> a = intbv(6, min=0, max=7)
          >>> len(a)
          3
          >>> a = intbv(6, min=-3, max=7)
          >>> len(a)
          4
          >>> a = intbv(6, min=-13, max=7)
          >>> len(a)
          5

   Bit indexing
       A  common  requirement in hardware design is access to the individual bits. The intbv class implements an
       indexing interface that provides access to the bits of the underlying  two's  complement  representation.
       The following illustrates bit index read access:

          >>> from myhdl import bin
          >>> a = intbv(24)
          >>> bin(a)
          '11000'
          >>> int(a[0])
          0
          >>> int(a[3])
          1
          >>> b = intbv(-23)
          >>> bin(b)
          '101001'
          >>> int(b[0])
          1
          >>> int(b[3])
          1
          >>> int(b[4])
          0

       We  use  the  bin  function  provide  by  MyHDL  because it shows the two's complement representation for
       negative values, unlike Python's builtin with the same name. Note that lower indices correspond  to  less
       significant bits. The following code illustrates bit index assignment:

          >>> bin(a)
          '11000'
          >>> a[3] = 0
          >>> bin(a)
          '10000'
          >>> a
          intbv(16)
          >>> b
          intbv(-23)
          >>> bin(b)
          '101001'
          >>> b[3] = 0
          >>> bin(b)
          '100001'
          >>> b
          intbv(-31)

   Bit slicing
       The intbv type also supports bit slicing, for both read access assignment. For example:

          >>> a = intbv(24)
          >>> bin(a)
          '11000'
          >>> a[4:1]
          intbv(4)
          >>> bin(a[4:1])
          '100'
          >>> a[4:1] = 0b001
          >>> bin(a)
          '10010'
          >>> a
          intbv(18)

       In  accordance  with  the most common hardware convention, and unlike standard Python, slicing ranges are
       downward.  As in standard Python, the slicing range is half-open: the highest index bit is not  included.
       Unlike standard Python however, this index corresponds to the leftmost item.

       Both  indices  can  be omitted from the slice.  If the rightmost index is omitted, it is 0 by default. If
       the leftmost index is omitted, the meaning is to access "all" higher order bits. For example:

          >>> bin(a)
          '11000'
          >>> bin(a[4:])
          '1000'
          >>> a[4:] = '0001'
          >>> bin(a)
          '10001'
          >>> a[:] = 0b10101
          >>> bin(a)
          '10101'

       The half-openness of a slice may seem awkward at first, but it helps to avoid  one-off  count  issues  in
       practice. For example, the slice a[8:] has exactly 8 bits. Likewise, the slice a[7:2] has 7-2=5 bits. You
       can  think about it as follows: for a slice [i:j], only bits below index i are included, and the bit with
       index j is the last bit included.

       When an intbv object is sliced, a new intbv  object  is  returned.   This  new  intbv  object  is  always
       positive,  and  the  value bounds are set up in accordance with the bit width specified by the slice. For
       example:

          >>> a = intbv(6, min=-3, max=7)
          >>> len(a)
          4
          >>> b = a[4:]
          >>> b
          intbv(6L)
          >>> len(b)
          4
          >>> b.min
          0
          >>> b.max
          16

       In the example, the original object is sliced with a slice equal to its bit width.  The  returned  object
       has  the  same  value  and  bit  width,  but  its value range consists of all positive values that can be
       represented by the bit width.

       The object returned by a slice is positive, even when the original object is negative:

          >>> a = intbv(-3)
          >>> bin(a, width=5)
          '11101'
          >>> b = a[5:]
          >>> b
          intbv(29L)
          >>> bin(b)
          '11101'

       In this example, the bit pattern of the two objects is identical within the bit width, but  their  values
       have opposite sign.

       Sometimes hardware engineers prefer to constrain an object by defining its bit width directly, instead of
       the range of allowed values. Using the slicing properties of the intbv class one can do that as follows:

          >>> a = intbv(24)[5:]

       What actually happens here is that first an unconstrained intbv is created, which is then sliced. Slicing
       an intbv returns a new intbv with the constraints set up appropriately.  Inspecting the object now shows:

          >>> a.min
          0
          >>> a.max
          32
          >>> len(a)
          5

       Note  that  the  max  attribute  is  32,  as  with  5 bits it is possible to represent the range 0 .. 31.
       Creating an intbv in this way is convenient but has the disadvantage  that  only  positive  value  ranges
       between 0 and a power of 2 can be specified.

   The modbv class
       In  hardware  modeling,  there  is  often  a need for the elegant modeling of wrap-around behavior. intbv
       instances do not support this automatically, as they assert that any assigned value is within  the  bound
       constraints.  However,  wrap-around  modeling  can  be  straightforward.   For  example,  the wrap-around
       condition for a counter is often decoded explicitly, as it is needed for other purposes. Also, the modulo
       operator provides an elegant one-liner in many scenarios:

          count.next = (count + 1) % 2**8

       However, some interesting cases are not supported by the intbv type.   For  example,  we  would  like  to
       describe a free running counter using a variable and augmented assignment as follows:

          count_var += 1

       This  is  not  possible  with the intbv type, as we cannot add the modulo behavior to this description. A
       similar problem exist for an augmented left shift as follows:

          shifter <<= 4

       To support these operations directly, MyHDL provides the modbv type. modbv is implemented as  a  subclass
       of   intbv.   The  two classes have an identical interface and work together in a straightforward way for
       arithmetic operations.  The only difference is how the bounds are handled: out-of-bound values result  in
       an  error with intbv, and in wrap-around with modbv. For example, the modulo counter above can be modeled
       as follows:

          count = Signal(modbv(0, min=0, max=2**8))
          ...
          count.next = count + 1

       The wrap-around behavior is defined in general as follows:

          val = (val - min) % (max - min) + min

       In a typical case when min==0, this reduces to:

          val = val % max

   Unsigned and signed representation
       intbv is designed to be as high level as possible. The underlying value of an intbv object  is  a  Python
       int,  which is represented as a two's complement number with "indefinite" bit width. The range bounds are
       only used for error checking, and to calculate the minimum required bit width for  representation.  As  a
       result, arithmetic can be performed like with normal integers.

       In  contrast,  HDLs  such  as  Verilog and VHDL typically require designers to deal with representational
       issues, especially for synthesizable code.  They provide low-level types like  signed  and  unsigned  for
       arithmetic. The rules for arithmetic with such types are much more complicated than with plain integers.

       In some cases it can be useful to interpret intbv objects in terms of "signed" and "unsigned". Basically,
       it  depends  on  attribute min.  if min < 0, then the object is "signed", otherwise it is "unsigned".  In
       particular, the bit width of a "signed" object will account for a sign bit, but  that  of  an  "unsigned"
       will  not,  because that would be redundant. From earlier sections, we have learned that the return value
       from a slicing operation is always "unsigned".

       In some applications, it is desirable to convert an "unsigned" intbv to  a "signed", in other  words,  to
       interpret the msb bit as a sign bit.  The msb bit is the highest order bit within the object's bit width.
       For this purpose, intbv provides the intbv.signed method. For example:

          >>> a = intbv(12, min=0, max=16)
          >>> bin(a)
          '1100'
          >>> b = a.signed()
          >>> b
          -4
          >>> bin(b, width=4)
          '1100'

       intbv.signed  extends  the msb bit into the higher-order bits of the underlying object value, and returns
       the result as an integer.  Naturally, for a "signed" the return value will always  be  identical  to  the
       original value, as it has the sign bit already.

       As an example let's take a 8 bit wide data bus that would be modeled as follows:

          data_bus = intbv(0)[8:]

       Now  consider  that  a complex number is transferred over this data bus. The upper 4 bits of the data bus
       are used for the real value and the lower 4 bits for the imaginary value. As real  and  imaginary  values
       have  a  positive  and  negative value range, we can slice them off from the data bus and convert them as
       follows:

          real.next = data_bus[8:4].signed()
          imag.next = data_bus[4:].signed()

   Structural modeling
   Introduction
       Hardware descriptions need to support the concepts of module instantiation and hierarchy.  In  MyHDL,  an
       instance  is  recursively  defined  as being either a sequence of instances, or a generator. Hierarchy is
       modeled by defining instances in a higher-level  function,  and  returning  them.   The  following  is  a
       schematic example of the basic case.

          from myhdl import block

          @block
          def top(...):
              ...
              instance_1 = module_1(...)
              instance_2 = module_2(...)
              ...
              instance_n = module_n(...)
              ...
              return instance_1, instance_2, ... , instance_n

       Note  that  MyHDL  uses  conventional  procedural  techniques  for  modeling  structure.   This  makes it
       straightforward to model more complex cases.

   Conditional instantiation
       To model conditional instantiation, we can select the returned  instance  under  parameter  control.  For
       example:

          from myhdl import block

          SLOW, MEDIUM, FAST = range(3)

          @block
          def top(..., speed=SLOW):
              ...
              def slowAndSmall():
                 ...
              ...
              def fastAndLarge():
                 ...
              if speed == SLOW:
                  return slowAndSmall()
              elif speed == FAST:
                  return fastAndLarge()
              else:
                  raise NotImplementedError

   Lists of instances and signals
       Python lists are easy to create. We can use them to model lists of instances.

       Suppose we have a top module that instantiates a single channel submodule, as follows:

          from myhdl import block, Signal

          @block
          def top(...):

              din = Signal(0)
              dout = Signal(0)
              clk = Signal(bool(0))
              reset = Signal(bool(0))

              channel_inst = channel(dout, din, clk, reset)

              return channel_inst

       If  we  wanted  to  support  an  arbitrary  number of channels, we can use lists of signals and a list of
       instances, as follows:

          from myhdl import block, Signal

          @block
          def top(..., n=8):

              din = [Signal(0) for i in range(n)]
              dout = [Signal(0) for in range(n)]
              clk = Signal(bool(0))
              reset = Signal(bool(0))
              channel_inst = [None for i in range(n)]

              for i in range(n):
                  channel_inst[i] = channel(dout[i], din[i], clk, reset)

              return channel_inst

   Converting between lists of signals and bit vectors
       Compared to HDLs such as VHDL and Verilog, MyHDL signals are less flexible for structural  modeling.  For
       example,  slicing  a signal returns a slice of the current value. For behavioral code, this is just fine.
       However, it implies that you cannot use such as slice in  structural  descriptions.  In  other  words,  a
       signal slice cannot be used as a signal.

       In  MyHDL,  you can address such cases by a concept called shadow signals. A shadow signal is constructed
       out of other signals and follows their value changes automatically.  For example, a _SliceSignal  follows
       the  value  of an index or a slice from another signal.  Likewise, A ConcatSignal follows the values of a
       number of signals as a concatenation.

       As an example, suppose we have a system with N requesters that need arbitration.  Each  requester  has  a
       request output and a grant input. To connect them in the system, we can use list of signals. For example,
       a list of request signals can be constructed as follows:

          request_list = [Signal(bool()) for i in range(M)]

       Suppose that an arbiter module is available that is instantiated as follows:

          arb = arbiter(grant_vector, request_vector, clock, reset)

       The  request_vector  input is a bit vector that can have any of its bits asserted. The grant_vector is an
       output bit vector with just a single bit asserted, or none.  Such a module  is  typically  based  on  bit
       vectors  because  they are easy to process in RTL code. In MyHDL, a bit vector is modeled using the intbv
       type.

       We need a way to "connect" the list of signals to the bit vector and vice versa. Of  course,  we  can  do
       this  with  explicit  code, but shadow signals can do this automatically. For example, we can construct a
       request_vector as a ConcatSignal object:

          request_vector = ConcatSignal(*reversed(request_list)

       Note that we reverse the list first. This is done because the index range of lists is the inverse of  the
       range of intbv bit vectors.  By reversing, the indices correspond to the same bit.

       The inverse problem exist for the grant_vector. It would be defined as follows:

          grant_vector = Signal(intbv(0)[M:])

       To  construct a list of signals that are connected automatically to the bit vector, we can use the Signal
       call interface to construct _SliceSignal objects:

          grant_list = [grant_vector(i) for i in range(M)]

       Note the round brackets used for this type of slicing. Also, it may not be necessary  to  construct  this
       list explicitly. You can simply use grant_vector(i) in an instantiation.

       To  decide when to use normal or shadow signals, consider the data flow. Use normal signals to connect to
       outputs. Use shadow signals to transform these signals so that they can be used as inputs.

   Inferring the list of instances
       In MyHDL, instances have to be returned explicitly by a top level  function.  It  may  be  convenient  to
       assemble   the list of instances automatically. For this purpose, MyHDL  provides the function instances.
       Using the first example in this section, it is used as follows:

          from myhdl import block, instances

          @block
          def top(...):
              ...
              instance_1 = module_1(...)
              instance_2 = module_2(...)
              ...
              instance_n = module_n(...)
              ...
              return instances()

       Function instances uses introspection to inspect the type of the local variables defined by  the  calling
       function.  All variables that comply with the definition of an instance are assembled in a list, and that
       list is returned.

   RTL modeling
   Introduction
       RTL (Register Transfer  Level)  is  a  modeling  abstraction  level  that  is  typically  used  to  write
       synthesizable  models.   Synthesis  refers  to  the  process by which an HDL description is automatically
       compiled into an implementation for an ASIC or FPGA.  This chapter describes how MyHDL supports it.

   Combinatorial logic
   Template
       Combinatorial logic is described with a code pattern as follows:

          from myhdl import block, always_comb

          @block
          def top(<parameters>):
              ...
              @always_comb
              def comb_logic():
                  <functional code>
              ...
              return comb_logic, ...

       The always_comb decorator describes combinatorial logic. The  name  refers  to  a  similar  construct  in
       SystemVerilog.  The  decorated  function  is a local function that specifies what happens when one of the
       input signals of the logic changes.  The always_comb decorator infers the input signals automatically. It
       returns a generator that is sensitive to all inputs, and that executes the  function  whenever  an  input
       changes.

   Example
       The following is an example of a combinatorial multiplexer

       To  verify  it,  we  will  simulate  the  logic  with some random patterns. The random module in Python's
       standard library comes in handy for such purposes.  The function randrange(n) returns  a  random  natural
       integer smaller than n.  It is used in the test bench code to produce random input values.

       It  is  often useful to keep the random values reproducible. This can be accomplished by providing a seed
       value as in the code. The run produces the following output:

   Sequential logic
   Template
       Sequential RTL models are sensitive to a clock edge. In addition,  they  may  be  sensitive  to  a  reset
       signal.  The always_seq decorator supports this model directly:

          from myhdl import block, always_seq

          @block
          def top(<parameters>, clock, ..., reset, ...):
              ...
              @always_seq(clock.posedge, reset=reset)
              def seq_logic():
                  <functional code>
              ...
              return seq_logic, ...

       The  always_seq decorator automatically infers the reset functionality.  It detects which signals need to
       be reset, and uses their initial values as the  reset  values.  The  reset  signal  itself  needs  to  be
       specified as a ResetSignal object. For example:

          reset = ResetSignal(0, active=0, isasync=True)

       The  first  parameter  specifies the initial value. The active parameter specifies the value on which the
       reset is active, and the isasync parameter specifies whether it is an asychronous (True) or a synchronous
       (False) reset. If no reset is needed, you can assign None  to  the  reset  parameter  in  the  always_seq
       parameter.

   Example
       The following code is a description of an incrementer with enable, and an asynchronous reset.

       For  the  test  bench, we will use an independent clock generator, stimulus generator, and monitor. After
       applying enough stimulus patterns, we can raise the StopSimulation exception to stop the simulation  run.
       The test bench for a small incrementer and a small number of patterns is a follows

       The simulation produces the following output

   Alternative template
       The  template  with  the  always_seq  decorator  is  convenient  as  it  infers  the  reset functionality
       automatically. Alternatively, you can use a more explicit template as follows:

          from myhdl import block, always

          @block
          def top(<parameters>, clock, ..., reset, ...):
              ...
              @always(clock.posedge, reset.negedge)
              def seq_logic():
                 if not reset:
                     <reset code>
                 else:
                     <functional code>

              return seq_logic,...

       With this template, the reset values have to be specified explicitly.

   Finite State Machine modeling
       Finite State Machine (FSM) modeling  is  very  common  in  RTL  design  and  therefore  deserves  special
       attention.

       For  code  clarity, the state values are typically represented by a set of identifiers. A standard Python
       idiom for this purpose is to assign a range of integers to a tuple of identifiers, like so

          >>> SEARCH, CONFIRM, SYNC = range(3)
          >>> CONFIRM
          1

       However, this technique has some drawbacks. Though it is  clearly  the  intention  that  the  identifiers
       belong  together, this information is lost as soon as they are defined. Also, the identifiers evaluate to
       integers, whereas a string representation of the identifiers would be preferable. To solve these  issues,
       we need an enumeration type.

       MyHDL  supports  enumeration  types  by  providing a function enum.  The arguments to enum are the string
       representations of the identifiers, and its return value is an  enumeration  type.  The  identifiers  are
       available as attributes of the type. For example

          >>> from myhdl import enum
          >>> t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
          >>> t_State
          <Enum: SEARCH, CONFIRM, SYNC>
          >>> t_State.CONFIRM
          CONFIRM

       We can use this type to construct a state signal as follows:

          state = Signal(t_State.SEARCH)

       As  an  example,  we  will use a framing controller FSM.  It is an imaginary example, but similar control
       structures are often found in telecommunication applications. Suppose that we need to find the  Start  Of
       Frame  (SOF)  position  of  an  incoming frame of bytes. A sync pattern detector continuously looks for a
       framing pattern and indicates it to the FSM with a syncFlag signal. When found, the FSM  moves  from  the
       initial  SEARCH state to the CONFIRM state.  When the syncFlag is confirmed on the expected position, the
       FSM declares SYNC, otherwise it falls back to the SEARCH state.  This FSM can be coded as follows

       At this point, we will use the example to demonstrate the MyHDL  support  for  waveform  viewing.  During
       simulation,  signal  changes  can  be  written to a VCD output file.  The VCD file can then be loaded and
       viewed in a waveform viewer tool such as gtkwave.

       The user interface of this feature consists of a single function, traceSignals.  To explain how it works,
       recall that in MyHDL, an instance is created by assigning the result of a function call  to  an  instance
       name. For example:

          tb_fsm = testbench()

       To enable VCD tracing, the instance should be created as follows instead:

          tb_fsm = traceSignals(testbench)

       Note  that  the first argument of traceSignals consists of the uncalled function. By calling the function
       under its control, traceSignals gathers information about the hierarchy and the signals to be traced.  In
       addition  to  a  function  argument,  traceSignals accepts an arbitrary number of non-keyword and keyword
       arguments that will be passed to the function call.

       A small test bench for our framing controller example, with signal tracing enabled, is shown below:

       When we run the test bench, it generates a VCD file called testbench.vcd. When we  load  this  file  into
       gtkwave, we can view the waveforms: [image]

       Signals  are  dumped  in a suitable format. This format is inferred at the Signal construction time, from
       the type of the initial value. In particular, bool signals are dumped as single bits.  (This  only  works
       starting  with Python 2.3, when bool has become a separate type).  Likewise, intbv signals with a defined
       bit width are dumped as bit vectors. To support the general case, other types of signals are dumped as  a
       string representation, as returned by the standard str function.

       WARNING:
          Support for literal string representations is not part of the VCD standard. It is specific to gtkwave.
          To generate a standard VCD file, you need to use signals with a defined bit width only.

   High level modeling
   Introduction
       To  write  synthesizable  models  in  MyHDL,  you  should  stick to the RTL templates shown in model-rtl.
       However, modeling in MyHDL is much more powerful than that.  Conceptually, MyHDL is a library for general
       event-driven modeling and simulation of hardware systems.

       There are many reasons why it can be useful to model at a higher abstraction level than RTL. For example,
       you can use MyHDL to verify architectural features, such as system throughput, latency and buffer  sizes.
       You  can  also  write  high  level  models  for specialized technology-dependent cores that are not going
       through synthesis. Last but not least, you can use MyHDL to write test benches that verify a system model
       or a synthesizable description.

       This chapter explores some of the options for high level modeling with MyHDL.

   Modeling with bus-functional procedures
       A bus-functional procedure is a reusable encapsulation of the low-level operations  needed  to  implement
       some  abstract  transaction  on  a  physical  interface.  Bus-functional procedures are typically used in
       flexible verification environments.

       Once again, MyHDL  uses  generator  functions  to  support  bus-functional  procedures.   In  MyHDL,  the
       difference  between  instances and bus-functional procedure calls comes from the way in which a generator
       function is used.

       As an example, we will design a bus-functional procedure of a simplified UART transmitter.  We  assume  8
       data  bits,  no  parity  bit, and a single stop bit, and we add print statements to follow the simulation
       behavior:

          T_9600 = int(1e9 / 9600)

          def rs232_tx(tx, data, duration=T_9600):

              """ Simple rs232 transmitter procedure.

              tx -- serial output data
              data -- input data byte to be transmitted
              duration -- transmit bit duration

              """

              print "-- Transmitting %s --" % hex(data)
              print "TX: start bit"
              tx.next = 0
              yield delay(duration)

              for i in range(8):
                  print "TX: %s" % data[i]
                  tx.next = data[i]
                  yield delay(duration)

              print "TX: stop bit"
              tx.next = 1
              yield delay(duration)

       This looks exactly like the generator  functions  in  previous  sections.  It  becomes  a  bus-functional
       procedure  when we use it differently. Suppose that in a test bench, we want to generate a number of data
       bytes to be transmitted. This can be modeled as follows:

          testvals = (0xc5, 0x3a, 0x4b)

          def stimulus():
              tx = Signal(1)
              for val in testvals:
                  txData = intbv(val)
                  yield rs232_tx(tx, txData)

       We use the bus-functional procedure call as a clause in a yield statement.  This introduces a fourth form
       of the yield statement: using a generator as a clause. Although this is a more dynamic usage than in  the
       previous  cases,  the meaning is actually very similar: at that point, the original generator should wait
       for the completion of a generator.  In this case, the original generator resumes  when  the  rs232_tx(tx,
       txData) generator returns.

       When simulating this, we get:

          -- Transmitting 0xc5 --
          TX: start bit
          TX: 1
          TX: 0
          TX: 1
          TX: 0
          TX: 0
          TX: 0
          TX: 1
          TX: 1
          TX: stop bit
          -- Transmitting 0x3a --
          TX: start bit
          TX: 0
          TX: 1
          TX: 0
          TX: 1
          ...

       We will continue with this example by designing the corresponding UART receiver bus-functional procedure.
       This will allow us to introduce further capabilities of MyHDL and its use of the yield statement.

       Until  now, the yield statements had a single clause. However, they can have multiple clauses as well. In
       that case, the generator resumes as soon as the wait  condition  specified  by  one  of  the  clauses  is
       satisfied. This corresponds to the functionality of sensitivity lists in Verilog and VHDL.

       For  example,  suppose  we  want  to design an UART receive procedure with a timeout.  We can specify the
       timeout condition while waiting for the start bit, as in the following generator function:

          def rs232_rx(rx, data, duration=T_9600, timeout=MAX_TIMEOUT):

              """ Simple rs232 receiver procedure.

              rx -- serial input data
              data -- data received
              duration -- receive bit duration

              """

              # wait on start bit until timeout
              yield rx.negedge, delay(timeout)
              if rx == 1:
                  raise StopSimulation, "RX time out error"

              # sample in the middle of the bit duration
              yield delay(duration // 2)
              print "RX: start bit"

              for i in range(8):
                  yield delay(duration)
                  print "RX: %s" % rx
                  data[i] = rx

              yield delay(duration)
              print "RX: stop bit"
              print "-- Received %s --" % hex(data)

       If the timeout condition is triggered, the receive bit rx will still be 1. In  that  case,  we  raise  an
       exception  to stop the simulation. The StopSimulation exception is predefined in MyHDL for such purposes.
       In the other case, we proceed by positioning the sample point in the middle  of  the  bit  duration,  and
       sampling the received data bits.

       When  a  yield  statement  has  multiple  clauses,  they can be of any type that is supported as a single
       clause, including generators. For example, we can verify the transmitter and receiver  generator  against
       each other by yielding them together, as follows:

          def test():
              tx = Signal(1)
              rx = tx
              rxData = intbv(0)
              for val in testvals:
                  txData = intbv(val)
                  yield rs232_rx(rx, rxData), rs232_tx(tx, txData)

       Both  forked  generators  will run concurrently, and the original generator will resume as soon as one of
       them finishes (which will be the transmitter in this case).  The simulation output  shows  how  the  UART
       procedures run in lockstep:

          -- Transmitting 0xc5 --
          TX: start bit
          RX: start bit
          TX: 1
          RX: 1
          TX: 0
          RX: 0
          TX: 1
          RX: 1
          TX: 0
          RX: 0
          TX: 0
          RX: 0
          TX: 0
          RX: 0
          TX: 1
          RX: 1
          TX: 1
          RX: 1
          TX: stop bit
          RX: stop bit
          -- Received 0xc5 --
          -- Transmitting 0x3a --
          TX: start bit
          RX: start bit
          TX: 0
          RX: 0
          ...

       For  completeness, we will verify the timeout behavior with a test bench that disconnects the rx from the
       tx signal, and we specify a small timeout for the receive procedure:

          def testTimeout():
              tx = Signal(1)
              rx = Signal(1)
              rxData = intbv(0)
              for val in testvals:
                  txData = intbv(val)
                  yield rs232_rx(rx, rxData, timeout=4*T_9600-1), rs232_tx(tx, txData)

       The simulation now stops with a timeout exception after a few transmit cycles:

          -- Transmitting 0xc5 --
          TX: start bit
          TX: 1
          TX: 0
          TX: 1
          StopSimulation: RX time out error

       Recall that the original generator resumes as soon as one  of  the  forked  generators  returns.  In  the
       previous  cases,  this is just fine, as the transmitter and receiver generators run in lockstep. However,
       it may be desirable to resume the caller only when all  of  the  forked  generators  have  finished.  For
       example,  suppose  that  we want to characterize the robustness of the transmitter and receiver design to
       bit duration differences. We can adapt our test bench as follows, to run  the  transmitter  at  a  faster
       rate:

          T_10200 = int(1e9 / 10200)

          def testNoJoin():
              tx = Signal(1)
              rx = tx
              rxData = intbv(0)
              for val in testvals:
                  txData = intbv(val)
                  yield rs232_rx(rx, rxData), rs232_tx(tx, txData, duration=T_10200)

       Simulating  this  shows  how the transmission of the new byte starts before the previous one is received,
       potentially creating additional transmission errors:

          -- Transmitting 0xc5 --
          TX: start bit
          RX: start bit
          ...
          TX: 1
          RX: 1
          TX: 1
          TX: stop bit
          RX: 1
          -- Transmitting 0x3a --
          TX: start bit
          RX: stop bit
          -- Received 0xc5 --
          RX: start bit
          TX: 0

       It is more likely that we want to characterize the design on a byte by byte  basis,  and  align  the  two
       generators  before  transmitting  each  byte.  In  MyHDL, this is done with the join function. By joining
       clauses together in a yield statement, we create a new clause that triggers only when all of  its  clause
       arguments have triggered. For example, we can adapt the test bench as follows:

          def testJoin():
              tx = Signal(1)
              rx = tx
              rxData = intbv(0)
              for val in testvals:
                  txData = intbv(val)
                  yield join(rs232_rx(rx, rxData), rs232_tx(tx, txData, duration=T_10200))

       Now, transmission of a new byte only starts when the previous one is received:

          -- Transmitting 0xc5 --
          TX: start bit
          RX: start bit
          ...
          TX: 1
          RX: 1
          TX: 1
          TX: stop bit
          RX: 1
          RX: stop bit
          -- Received 0xc5 --
          -- Transmitting 0x3a --
          TX: start bit
          RX: start bit
          TX: 0
          RX: 0

   Modeling memories with built-in types
       Python has powerful built-in data types that can be useful to model hardware memories. This can be merely
       a matter of putting an interface around some data type operations.

       For  example,  a  dictionary  comes in handy to model sparse memory structures. (In other languages, this
       data type is called  associative array, or hash table.) A sparse memory is one in which only a small part
       of the addresses is used in a particular application or simulation. Instead of statically allocating  the
       full  address  space,  which can be large, it is better to dynamically allocate the needed storage space.
       This is exactly what a dictionary provides. The following is an example of a sparse memory model:

          def sparseMemory(dout, din, addr, we, en, clk):

              """ Sparse memory model based on a dictionary.

              Ports:
              dout -- data out
              din -- data in
              addr -- address bus
              we -- write enable: write if 1, read otherwise
              en -- interface enable: enabled if 1
              clk -- clock input

              """

              memory = {}

              @always(clk.posedge)
              def access():
                  if en:
                      if we:
                          memory[addr.val] = din.val
                      else:
                          dout.next = memory[addr.val]

              return access

       Note how we use the val attribute of the din signal, as we don't want to store the signal object  itself,
       but its current value. Similarly, we use the val attribute of the addr signal as the dictionary key.

       In  many  cases,  MyHDL  code uses a signal's current value automatically when there is no ambiguity: for
       example, when a signal is used in an expression. However, in other cases, such as in  this  example,  you
       have  to refer to the value explicitly: for example, when the Signal is used as a dictionary key, or when
       it is not used in an expression.  One option is to use the val attribute, as in  this  example.   Another
       possibility  is  to  use  the int() or bool() functions to typecast the Signal to an integer or a boolean
       value. These functions are also useful with intbv objects.

       As a second example, we will demonstrate how to use a list to model a synchronous fifo:

          def fifo(dout, din, re, we, empty, full, clk, maxFilling=sys.maxint):

              """ Synchronous fifo model based on a list.

              Ports:
              dout -- data out
              din -- data in
              re -- read enable
              we -- write enable
              empty -- empty indication flag
              full -- full indication flag
              clk -- clock input

              Optional parameter:
              maxFilling -- maximum fifo filling, "infinite" by default

              """

              memory = []

              @always(clk.posedge)
              def access():
                  if we:
                      memory.insert(0, din.val)
                  if re:
                      dout.next = memory.pop()
                  filling = len(memory)
                  empty.next = (filling == 0)
                  full.next = (filling == maxFilling)

              return access

       Again, the model is merely a MyHDL interface around some operations on a list: insert to insert  entries,
       pop to retrieve them, and len to get the size of a Python object.

   Modeling errors using exceptions
       In  the previous section, we used Python data types for modeling. If such a type is used inappropriately,
       Python's run time error system will come into  play.  For  example,  if  we  access  an  address  in  the
       sparseMemory  model  that  was  not  initialized before, we will get a traceback similar to the following
       (some lines omitted for clarity):

          Traceback (most recent call last):
          ...
            File "sparseMemory.py", line 31, in access
              dout.next = memory[addr.val]
          KeyError: Signal(51)

       Similarly, if the fifo is empty, and we attempt to read from it, we get:

          Traceback (most recent call last):
          ...
            File "fifo.py", line 34, in fifo
              dout.next = memory.pop()
          IndexError: pop from empty list

       Instead of these low level errors, it may be preferable to define errors  at  the  functional  level.  In
       Python,  this  is  typically  done  by  defining  a  custom  Error exception, by subclassing the standard
       Exception class. This exception is then raised explicitly when an error condition occurs.

       For example, we can change the sparseMemory function as follows (with  the  doc  string  is  omitted  for
       brevity):

          class Error(Exception):
              pass

          def sparseMemory2(dout, din, addr, we, en, clk):

              memory = {}

              @always(clk.posedge)
              def access():
                  if en:
                      if we:
                          memory[addr.val] = din.val
                      else:
                          try:
                              dout.next = memory[addr.val]
                          except KeyError:
                              raise Error, "Uninitialized address %s" % hex(addr)

              return access

       This  works  by  catching  the  low  level  data type exception, and raising the custom exception with an
       appropriate error message instead.  If the sparseMemory function is defined in a  module  with  the  same
       name, an access error is now reported as follows:

          Traceback (most recent call last):
          ...
            File "sparseMemory.py", line 61, in access
              raise Error, "Uninitialized address %s" % hex(addr)
          Error: Uninitialized address 0x33

       Likewise, the fifo function can be adapted as follows, to report underflow and overflow errors:

          class Error(Exception):
              pass

          def fifo2(dout, din, re, we, empty, full, clk, maxFilling=sys.maxint):

              memory = []

              @always(clk.posedge)
              def access():
                  if we:
                      memory.insert(0, din.val)
                  if re:
                      try:
                          dout.next = memory.pop()
                      except IndexError:
                          raise Error, "Underflow -- Read from empty fifo"
                  filling = len(memory)
                  empty.next = (filling == 0)
                  full.next = (filling == maxFilling)
                  if filling > maxFilling:
                      raise Error, "Overflow -- Max filling %s exceeded" % maxFilling

              return access

       In  this  case,  the underflow error is detected as before, by catching a low level exception on the list
       data type. On the other hand, the overflow error is detected by a regular check  on  the  length  of  the
       list.

   Object oriented modeling
       The  models  in the previous sections used high-level built-in data types internally. However, they had a
       conventional RTL-style interface.  Communication with such a module is  done  through  signals  that  are
       attached to it during instantiation.

       A  more  advanced  approach  is  to  model hardware blocks as objects. Communication with objects is done
       through method calls. A method encapsulates all details of a certain task performed by the object. As  an
       object  has  a  method interface instead of an RTL-style hardware interface, this is a much  higher level
       approach.

       As an example, we will design a synchronized queue object.  Such an object can be filled by producer, and
       independently read by a consumer. When the queue is empty, the consumer should  wait  until  an  item  is
       available. The queue can be modeled as an object with a put(item) and a get method, as follows:

          from myhdl import *

          def trigger(event):
              event.next = not event

          class queue:
              def __init__(self):
                 self.l = []
                 self.sync = Signal(0)
                 self.item = None
              def put(self,item):
                 # non time-consuming method
                 self.l.append(item)
                 trigger(self.sync)
              def get(self):
                 # time-consuming method
                 if not self.l:
                    yield self.sync
                 self.item = self.l.pop(0)

       The queue object constructor initializes an internal list to hold items, and a sync signal to synchronize
       the  operation  between  the  methods.   Whenever put puts an item in the queue, the signal is triggered.
       When the get method sees that the list is empty, it waits on the trigger first. get is a generator method
       because  it may consume time. As the yield statement is used in MyHDL  for  timing  control,  the  method
       cannot "yield" the item. Instead, it makes it available in the item instance variable.

       To  test  the  queue  operation, we will model a producer and a consumer in the test bench.  As a waiting
       consumer should not block a whole system, it should run in a concurrent "thread".  As  always  in  MyHDL,
       concurrency  is  modeled  by Python generators. Producer and consumer will thus run independently, and we
       will monitor their operation through some print statements:

          q = queue()

          def Producer(q):
              yield delay(120)
              for i in range(5):
                  print "%s: PUT item %s" % (now(), i)
                  q.put(i)
                  yield delay(max(5, 45 - 10*i))

          def Consumer(q):
              yield delay(100)
              while 1:
                  print "%s: TRY to get item" % now()
                  yield q.get()
                  print "%s: GOT item %s" % (now(), q.item)
                  yield delay(30)

          def main():
              P = Producer(q)
              C = Consumer(q)
              return P, C

          sim = Simulation(main())
          sim.run()

       Note that the generator method get is called in a yield statement  in  the  Consumer  function.  The  new
       generator  will take over from Consumer, until it is done. Running this test bench produces the following
       output:

          % python queue.py
          100: TRY to get item
          120: PUT item 0
          120: GOT item 0
          150: TRY to get item
          165: PUT item 1
          165: GOT item 1
          195: TRY to get item
          200: PUT item 2
          200: GOT item 2
          225: PUT item 3
          230: TRY to get item
          230: GOT item 3
          240: PUT item 4
          260: TRY to get item
          260: GOT item 4
          290: TRY to get item
          StopSimulation: No more events

   Unit testing
   Introduction
       Many aspects in the design flow of modern digital hardware design can be viewed  as  a  special  kind  of
       software  development.  From that viewpoint, it is a natural question whether advances in software design
       techniques can not also be applied to hardware design.

       One software design approach that deserves attention is Extreme Programming (XP). It is a fascinating set
       of techniques and guidelines that often seems to go against the conventional wisdom. On other  occasions,
       XP  just  seems  to  emphasize the common sense, which doesn't always coincide with common practice.  For
       example, XP stresses the importance of normal workweeks, if we are to have the fresh mind needed for good
       software development.

       It is not my intention nor qualification to present a tutorial on Extreme Programming. Instead,  in  this
       section I will highlight one XP concept which I think is very relevant to hardware design: the importance
       and methodology of unit testing.

   The importance of unit tests
       Unit  testing  is  one of the corner stones of Extreme Programming. Other XP concepts, such as collective
       ownership of code and continuous refinement, are  only  possible  by  having  unit  tests.  Moreover,  XP
       emphasizes  that writing unit tests should be automated, that they should test everything in every class,
       and that they should run perfectly all the time.

       I believe that these concepts apply directly to hardware design. In addition, unit tests  are  a  way  to
       manage  simulation  time.  For example, a state machine that runs very slowly on infrequent events may be
       impossible to verify at the system level, even on the fastest simulator. On the other  hand,  it  may  be
       easy to verify it exhaustively in a unit test, even on the slowest simulator.

       It is clear that unit tests have compelling advantages. On the other hand, if we need to test everything,
       we  have  to  write lots of unit tests. So it should be easy and pleasant to create, manage and run them.
       Therefore, XP emphasizes the need for a unit test framework that supports these tasks. In  this  chapter,
       we  will  explore the use of the unittest module from the standard Python library for creating unit tests
       for hardware designs.

   Unit test development
       In this section, we will informally explore the application of unit test techniques to  hardware  design.
       We  will  do  so  by  a  (small)  example:  testing  a  binary  to  Gray encoder as introduced in section
       hwtypes-indexing.

   Defining the requirements
       We start by defining the requirements. For a Gray encoder, we want to the output to comply with Gray code
       characteristics. Let's define a code as a list of codewords, where a codeword is a bit string. A code  of
       order n has 2**n codewords.

       A well-known characteristic is the one that Gray codes are all about:

       Consecutive codewords in a Gray code should differ in a single bit.

       Is  this sufficient? Not quite: suppose for example that an implementation returns the lsb of each binary
       input. This would comply with the requirement, but is obviously not what we want. Also, we don't want the
       bit width of Gray codewords to exceed the bit width of the binary codewords.

       Each codeword in a Gray code of order n must occur exactly once in the binary code of the same order.

       With the requirements written down we can proceed.

   Writing the test first
       A fascinating guideline in the XP world is to write the unit test first.  That  is,  before  implementing
       something,  first  write the test that will verify it.  This seems to go against our natural inclination,
       and certainly against  common  practices.  Many  engineers  like  to  implement  first  and  think  about
       verification afterwards.

       But if you think about it, it makes a lot of sense to deal with verification first. Verification is about
       the  requirements  only  --- so your thoughts are not yet cluttered with implementation details. The unit
       tests are an executable description of the requirements, so they will be better understood and it will be
       very clear what needs to be done. Consequently, the  implementation  should  go  smoother.  Perhaps  most
       importantly,  the  test is available when you are done implementing, and can be run anytime by anybody to
       verify changes.

       Python has a standard unittest module that facilitates writing, managing and  running  unit  tests.  With
       unittest,  a  test  case is  written by creating a class that inherits from unittest.TestCase. Individual
       tests are created by methods of that class: all method names that start with test are  considered  to  be
       tests of the test case.

       We  will  define  a  test  case  for  the  Gray  code  properties,  and then write a test for each of the
       requirements. The outline of the test case class is as follows:

          import unittest

          class TestGrayCodeProperties(unittest.TestCase):

              def testSingleBitChange(self):
               """Check that only one bit changes in successive codewords."""
               ....

              def testUniqueCodeWords(self):
              """Check that all codewords occur exactly once."""
              ....

       Each method will be a small test bench that tests a single requirement. To write the tests, we don't need
       an implementation of the Gray encoder, but we do need the interface of the design. We can specify this by
       a dummy implementation, as follows:

       For the first requirement, we will test all  consecutive input numbers, and compare  the  current  output
       with  the  previous  one  For  each  input, we check that the difference is exactly a single bit. For the
       second requirement, we will test all input numbers and put the result in a list. The requirement  implies
       that  if  we  sort the result list, we should get a range of numbers. For both requirements, we will test
       all Gray codes up to a certain order MAX_WIDTH.  The test code looks as follows:

       Note how the actual check is performed by a self.assertEqual method,  defined  by  the  unittest.TestCase
       class. Also, we have factored out running the tests for all Gray codes in a separate method runTests.

   Test-driven implementation
       With the test written, we begin with the implementation. For illustration purposes, we will intentionally
       write some incorrect implementations to see how the test behaves.

       The  easiest way to run tests defined with the unittest framework, is to put a call to its main method at
       the end of the test module:

          unittest.main()

       Let's run the test using the dummy Gray encoder shown earlier:

          % python test_gray_properties.py
          testSingleBitChange (__main__.TestGrayCodeProperties)
          Check that only one bit changes in successive codewords. ... ERROR
          testUniqueCodeWords (__main__.TestGrayCodeProperties)
          Check that all codewords occur exactly once. ... ERROR

       As expected, this fails completely. Let us try an incorrect implementation, that puts the lsb of  in  the
       input on the output:

       Running the test produces:

          python test_gray_properties.py
          testSingleBitChange (__main__.TestGrayCodeProperties)
          Check that only one bit changes in successive codewords. ... ok
          testUniqueCodeWords (__main__.TestGrayCodeProperties)
          Check that all codewords occur exactly once. ... FAIL

          ======================================================================
          FAIL: testUniqueCodeWords (__main__.TestGrayCodeProperties)
          Check that all codewords occur exactly once.
          ----------------------------------------------------------------------
          Traceback (most recent call last):
            File "test_gray_properties.py", line 42, in testUniqueCodeWords
              self.runTests(test)
            File "test_gray_properties.py", line 53, in runTests
              sim.run(quiet=1)
            File "/home/jand/dev/myhdl/myhdl/_Simulation.py", line 154, in run
              waiter.next(waiters, actives, exc)
            File "/home/jand/dev/myhdl/myhdl/_Waiter.py", line 127, in next
              clause = next(self.generator)
            File "test_gray_properties.py", line 40, in test
              self.assertEqual(actual, expected)
          AssertionError: Lists differ: [0, 0, 1, 1] != [0, 1, 2, 3]

          First differing element 1:
          0
          1

          - [0, 0, 1, 1]
          + [0, 1, 2, 3]

          ----------------------------------------------------------------------
          Ran 2 tests in 0.083s

          FAILED (failures=1)

       Now  the  test  passes  the  first  requirement,  as  expected,  but fails the second one. After the test
       feedback, a full traceback is shown that can help to debug the test output.

       Finally, we use a correct implementation:

       Now the tests pass:

   Additional requirements
       In the previous section, we concentrated on the general requirements of a Gray code. It  is  possible  to
       specify  these  without  specifying  the actual code. It is easy to see that there are several codes that
       satisfy these requirements. In good XP style, we only tested the requirements and nothing more.

       It may be that more control is needed. For example, the requirement may be for a particular code, instead
       of compliance with general properties. As an illustration, we will show how to test for the original Gray
       code, which is one specific instance that satisfies the requirements of the previous  section.   In  this
       particular case, this test will actually be easier than the previous one.

       We denote the original Gray code of order n as Ln. Some examples:

          L1 = ['0', '1']
          L2 = ['00', '01', '11', '10']
          L3 = ['000', '001', '011', '010', '110', '111', '101', 100']

       It is possible to specify these codes by a recursive algorithm, as follows:

       1. L1 = ['0', '1']

       2. Ln+1  can  be obtained from Ln as follows. Create a new code Ln0 by prefixing all codewords of Ln with
          '0'. Create another new code Ln1 by prefixing all codewords of Ln with '1', and reversing their order.
          Ln+1 is the concatenation of Ln0 and Ln1.

       Python is well-known for its elegant algorithmic descriptions, and this is a good example. We  can  write
       the algorithm in Python as follows:

       The  code  ['0' + codeword for ...] is called a list comprehension. It is a concise way to describe lists
       built by short computations in a for loop.

       The requirement is now that the output code matches the expected code Ln. We use the nextLn  function  to
       compute the expected result. The new test case code is as follows:

       As it happens, our implementation is apparently an original Gray code:

   Co-simulation with Verilog
   Introduction
       One  of the most exciting possibilities of MyHDLis to use it as a hardware verification language (HVL). A
       HVL is a language used to write test benches and verification environments, and to control simulations.

       Nowadays, it is generally acknowledged that HVLs should be equipped with modern software techniques, such
       as object orientation. The reason is that verification it the most complex and time-consuming task of the
       design process. Consequently, every useful technique is welcome. Moreover, test benches are not  required
       to be implementable. Therefore, unlike with synthesizable code, there are no constraints on creativity.

       Technically,  verification  of  a design implemented in another language requires co-simulation. MyHDL is
       enabled for co-simulation with any HDL simulator that has a  procedural  language  interface  (PLI).  The
       MyHDLside  is  designed  to  be  independent  of  a particular simulator, On the other hand, for each HDL
       simulator a specific PLI module will have to be written in C. Currently, the MyHDL release contains a PLI
       module for two Verilog simulators: Icarus and Cver.

   The HDL side
       To introduce co-simulation, we will continue to use the Gray encoder example from the previous  chapters.
       Suppose  that we want to synthesize it and write it in Verilog for that purpose. Clearly we would like to
       reuse our unit test verification environment.

       To start, let's recall how the Gray encoder in MyHDL looks like:

       To show the co-simulation flow, we don't need the Verilog implementation yet,  but  only  the  interface.
       Our Gray encoder in Verilog would have the following interface:

          module bin2gray(B, G);

             parameter width = 8;
             input [width-1:0]  B;
             output [width-1:0] G;
             ....

       To  write a test bench, one creates a new module that instantiates the design under test (DUT).  The test
       bench declares nets and regs (or signals in  VHDL)  that  are  attached  to  the  DUT,  and  to  stimulus
       generators and response checkers.  In an all-HDL flow, the generators and checkers are written in the HDL
       itself,  but we will want to write them in MyHDL. To make the connection, we need to declare which regs &
       nets are driven and read by the MyHDLsimulator. For our example, this is done as follows:

          module dut_bin2gray;

             reg [`width-1:0] B;
             wire [`width-1:0] G;

             initial begin
                $from_myhdl(B);
                $to_myhdl(G);
             end

             bin2gray dut (.B(B), .G(G));
             defparam dut.width = `width;

          endmodule

       The $from_myhdl task call declares which regs are driven by MyHDL, and the $to_myhdl task call which regs
       & nets are read by it. These tasks take an arbitrary number of arguments.  They  are  defined  in  a  PLI
       module written in C and made available in a simulator-dependent manner.  In Icarus Verilog, the tasks are
       defined in a myhdl.vpi module that is compiled from C source code.

   The MyHDL side
       MyHDL  supports co-simulation by a Cosimulation object.  A Cosimulation object must know how to run a HDL
       simulation. Therefore, the first argument to its constructor is a command string to execute a simulation.

       The way to generate and run an simulation executable is simulator  dependent.   For  example,  in  Icarus
       Verilog,  a  simulation  executable  for  our  example  can  be obtained obtained by running the iverilog
       compiler as follows:

          % iverilog -o bin2gray -Dwidth=4 bin2gray.v dut_bin2gray.v

       This generates a bin2gray executable for a parameter width of 4, by compiling  the  contributing  Verilog
       files.

       The simulation itself is run by the vvp command:

          % vvp -m ./myhdl.vpi bin2gray

       This  runs  the bin2gray simulation, and specifies to use the myhdl.vpi PLI module present in the current
       directory. (This is  just a command line usage example; actually simulating with the myhdl.vpi module  is
       only meaningful from a Cosimulation object.)

       We  can use a Cosimulation object to provide a HDL version of a design to the MyHDL simulator. Instead of
       a generator function, we write a function that returns a Cosimulation object. For  our  example  and  the
       Icarus Verilog simulator, this is done as follows:

          import os

          from myhdl import Cosimulation

          cmd = "iverilog -o bin2gray.o -Dwidth=%s " + \
                "../../test/verilog/bin2gray.v " + \
                "../../test/verilog/dut_bin2gray.v "

          def bin2gray(B, G):
              width = len(B)
              os.system(cmd % width)
              return Cosimulation("vvp -m ../myhdl.vpi bin2gray.o", B=B, G=G)

       After  the executable command argument, the Cosimulation constructor takes an arbitrary number of keyword
       arguments. Those arguments make the link between MyHDL Signals and HDL nets, regs, or signals,  by  named
       association. The keyword is the name of an argument in a $to_myhdl or $from_myhdl call; the argument is a
       MyHDL Signal.

       With  all this in place, we can now use the existing unit test to verify the Verilog implementation. Note
       that we kept the same name and parameters for the the bin2gray function: all we need to do is to  provide
       this alternative definition to the existing unit test.

       Let's try it on the Verilog design:

          module bin2gray(B, G);

             parameter width = 8;
             input [width-1:0]  B;
             output [width-1:0] G;

             assign G = (B >> 1) ^ B;

          endmodule // bin2gray

       When we run our unit tests, we get:

          % python test_gray.py
          testSingleBitChange (test_gray_properties.TestGrayCodeProperties)
          Check that only one bit changes in successive codewords. ... ok
          testUniqueCodeWords (test_gray_properties.TestGrayCodeProperties)
          Check that all codewords occur exactly once. ... ok
          testOriginalGrayCode (test_gray_original.TestOriginalGrayCode)
          Check that the code is an original Gray code. ... ok

          ----------------------------------------------------------------------
          Ran 3 tests in 0.706s

          OK

   Restrictions
       In  the ideal case, it should be possible to simulate any HDL description seamlessly with MyHDL. Moreover
       the communicating signals at each side should act transparently as a single one, enabling fully race free
       operation.

       For various reasons, it may not be possible or desirable to achieve full generality. As anyone  that  has
       developed  applications with the Verilog PLI can testify, the restrictions in a particular simulator, and
       the  differences over various simulators, can  be  quite   frustrating.  Moreover,  full  generality  may
       require  a  disproportionate amount of development work compared to a slightly less general solution that
       may be sufficient for the target application.

       Consequently, I have tried to achieve a solution which is  simple  enough  so  that  one  can  reasonably
       expect that any PLI-enabled simulator can support it, and that is relatively easy to verify and maintain.
       At the same time, the solution is sufficiently general  to cover the target application space.

       The  result  is  a  compromise  that  places certain restrictions on the HDL code. In this section, these
       restrictions  are presented.

   Only passive HDL can be co-simulated
       The most important restriction of the MyHDL co-simulation solution is that  only  "passive"  HDL  can  be
       co-simulated.   This means that the HDL code should not contain any statements with time delays. In other
       words, the MyHDL simulator should be the master of time;  in  particular,  any  clock  signal  should  be
       generated at the MyHDL side.

       At  first  this  may  seem like an important restriction, but if one considers the target application for
       co-simulation, it probably isn't.

       MyHDL supports co-simulation so that test benches for HDL  designs  can  be  written  in  Python.   Let's
       consider  the  nature  of the target HDL designs. For high-level, behavioral models that are not intended
       for implementation, it should come as no surprise that I would recommend to write them in MyHDL directly;
       that is one of the goals of the MyHDL effort. Likewise, gate level designs with annotated timing are  not
       the target application: static timing analysis is a much better verification method for such designs.

       Rather,  the  targeted HDL designs are naturally models that are intended for implementation, most likely
       through synthesis. As time delays are meaningless in synthesizable code, the  restriction  is  compatible
       with the target application.

   Race sensitivity issues
       In a typical RTL code, some events cause other events to occur in the same time step. For example, when a
       clock signal triggers some signals may change in the same time step. For race-free operation, an HDL must
       differentiate between such events within a time step. This is done by the concept of "delta" cycles. In a
       fully general, race free co-simulation, the co-simulators would communicate at the level of delta cycles.
       However, in MyHDL co-simulation, this is not entirely the case.

       Delta  cycles  from  the  MyHDL  simulator  toward  the  HDL co-simulator are preserved.  However, in the
       opposite direction, they are not. The signals changes are only returned to the MyHDL simulator after  all
       delta cycles have been performed in the HDL co-simulator.

       What  does  this  mean? Let's start with the good news. As explained in the previous section, the concept
       behind MyHDL co-simulation implies that clocks are generated at the MyHDL side.  When using a MyHDL clock
       and its corresponding HDL signal directly as a clock, co-simulation is race free.  In  other  words,  the
       case that most closely reflects the MyHDL co-simulation approach, is race free.

       The  situation  is different when you want to use a signal driven by the HDL (and the corresponding MyHDL
       signal) as a clock.  Communication triggered by such a clock is not race free. The solution is  to  treat
       such  an  interface as a chip interface instead of an RTL interface.  For example, when data is triggered
       at positive clock edges, it can safely be sampled at negative clock edges.  Alternatively, the MyHDL data
       signals can be declared with a delay value, so that they are guaranteed to change after the clock edge.

   Implementation notes
          This section requires some knowledge of PLI terminology.

       Enabling a simulator for co-simulation requires a PLI module written in C. In Verilog, the PLI is part of
       the "standard".  However, different simulators implement different versions and portions of the standard.
       Worse yet, the behavior of certain PLI callbacks is not defined on some essential points.  As  a  result,
       one  should  plan  to  write  or  at least customize a specific PLI module for any simulator. The release
       contains a PLI module for the open source Icarus and Cver simulators.

       This section documents the current approach  and  status  of  the  PLI  module  implementation  and  some
       reflections on future implementations.

   Icarus Verilog
   Delta cycle implementation
       To  make  co-simulation  work, a specific type of PLI callback is needed. The callback should be run when
       all pending events have been processed, while allowing the creation of new events  in  the  current  time
       step  (e.g.  by  the  MyHDL  simulator).   In  some Verilog simulators, the cbReadWriteSync callback does
       exactly that. However, in others, including Icarus, it does not. The callback's  behavior  is  not  fully
       standardized;  some  simulators  run  the  callback  before  non-  blocking  assignment  events have been
       processed.

       Consequently, I had to look for a workaround. One half of the  solution  is  to  use  the  cbReadOnlySync
       callback.   This callback runs after all pending events have been processed.  However, it does not permit
       one to create new events in the current time step.  The second half of the solution is to map MyHDL delta
       cycles onto real Verilog time steps.  Note that fortunately I  had  some  freedom  here  because  of  the
       restriction that only passive HDL code can be co-simulated.

       I  chose  to  make  the  time  granularity  in the Verilog simulator a 1000 times finer than in the MyHDL
       simulator. For each MyHDL time step, 1000 Verilog time steps are available for  MyHDL  delta  cycles.  In
       practice,  only  a few delta cycles per time step should be needed. Exceeding this limit almost certainly
       indicates a design error; the limit is checked at run-time.  The  factor  1000  also  makes  it  easy  to
       distinguish "real" time from delta cycle time when printing out the Verilog time.

   Passive Verilog check
       As  explained before, co-simulated Verilog should not contain delay statements.  Ideally, there should be
       a run-time check to flag non-compliant code. However, there is currently no  such  check  in  the  Icarus
       module.

       The  check  can  be written using the cbNextSimTime VPI callback in Verilog.  However, Icarus 0.7 doesn't
       support this callback. In the meantime, support for it has been added to the Icarus  development  branch.
       When Icarus 0.8 is released, a check will be added.

       In  the  mean  time,  just  don't  do this. It may appear to "work" but it really won't as events will be
       missed over the co-simulation interface.

   Cver
       MyHDL co-simulation is supported with the open source Verilog simulator Cver.  The PLI module is based on
       the one for Icarus and basically has the  same  functionality.  Only  some  cosmetic  modifications  were
       required.

   Other Verilog simulators
       The  Icarus  module  is  written  with VPI calls, which are provided by the most recent generation of the
       Verilog PLI. Some simulators may only  support  TF/ACC  calls,  requiring  a  complete  redesign  of  the
       interface module.

       If the simulator supports VPI, the Icarus module should be reusable to a large extent. However, it may be
       possible  to  improve  on  it.   The  workaround to support delta cycles described in Section Delta cycle
       implementation may not be necessary. In some simulators, the cbReadWriteSync callback  occurs  after  all
       events  (including  non-blocking assignments) have been processed. In that case, the functionality can be
       supported without a finer time granularity in the Verilog simulator.

       There are also Verilog standardization efforts underway to resolve the ambiguity of  the  cbReadWriteSync
       callback.  The  solution will be to introduce new, well defined callbacks. From reading some proposals, I
       conclude that the cbEndOfSimTime callback would provide the required functionality.

       The MyHDL project currently has no access to commercial Verilog simulators, so progress in  co-simulation
       support  depends  on  external  interest and participation. Users have reported that they are using MyHDL
       co-simulation with the simulators from Aldec and Modelsim.

   Interrupted system calls
       The PLI module  uses  read  and  write  system  calls  to  communicate  between  the  co-simulators.  The
       implementation  assumes  that  these  calls  are  restarted  automatically  by  the operating system when
       interrupted. This is apparently what happens on the Linux box on which MyHDL is developed.

       It is known how non-restarted interrupted system calls should be handled, but currently such code  cannot
       be tested on the MyHDL development platform. Also, it is not clear whether this is still a relevant issue
       with  modern  operating  systems.  Therefore,  this issue has not been addressed at this moment. However,
       assertions have been included that should trigger when this situation occurs.

       Whenever an assertion fires in the PLI module, please report it.  The same holds  for  Python  exceptions
       that cannot be easily explained.

   What about VHDL?
       It  would  be  nice  to  have an interface to VHDL simulators such as the Modelsim VHDL simulator. Let us
       summarize the requirements to accomplish that:

       • We need a procedural interface to the internals of the simulator.

       • The procedural interface should be a widely used industry standard so that we can  reuse  the  work  in
         several simulators.

       • MyHDL  is  an  open-source  project and therefore there should be also be an open-source simulator that
         implements the procedural interface.

       vpi for Verilog matches these requirements. It is  a  widely  used  standard  and  is  supported  by  the
       open-source Verilog simulators Icarus and cver.

       However,  for  VHDL  the situation is different. While there exists a standard called vhpi, it  much less
       popular than vpi. Also, to our knowledge there is only one credible open source VHDL simulator (GHDL) and
       it is unclear whether it has vhpi capabilities that are powerful enough for MyHDL's purposes.

       Consequently, the development of co-simulation for VHDL is currently  on  hold.  For  some  applications,
       there is an alternative: see conv-testbench.

   Conversion to Verilog and VHDL
   Introduction
       Subject  to  some  limitations,  MyHDL supports the automatic conversion of MyHDL code to Verilog or VHDL
       code. This feature provides a path from MyHDL into a standard Verilog or VHDL based design environment.

       This chapter describes the concepts of conversion. Concrete  examples  can  be  found  in  the  companion
       chapter conv-usage.

   Solution description
       To  be  convertible,  the  hardware  description  should  satisfy  certain  restrictions,  defined as the
       convertible subset. This is described in detail in The convertible subset.

       A convertible design can be converted to an equivalent model in  Verilog  or  VHDL,  using  the  function
       toVerilog or toVHDL  from the MyHDL library.

       When  the  design  is  intended  for  implementation  a third-party synthesis tool is used to compile the
       Verilog or VHDL model into an implementation for an ASIC or FPGA. With this step, there is  an  automated
       path from a hardware description in Python to an FPGA or ASIC implementation.

       The conversion does not start from source files, but from an instantiated design that has been elaborated
       by  the  Python  interpreter. The converter uses the Python profiler to track the interpreter's operation
       and to infer the design structure and name spaces. It then selectively compiles pieces of source code for
       additional analysis and for conversion.

   Features
       Conversion after elaboration
              Elaboration refers to the initial processing of a hardware description to achieve a representation
              of a design instance that  is  ready  for  simulation  or  synthesis.  In  particular,  structural
              parameters  and  constructs are processed in this step. In MyHDL, the Python interpreter itself is
              used for elaboration.  A Simulation object is constructed  with  elaborated  design  instances  as
              arguments.  Likewise, conversion works on an elaborated design instance. The Python interpreter is
              thus used as much as possible.

       Arbitrarily complex structure
              As  the  conversion works on an elaborated design instance, any modeling constraints only apply to
              the leaf elements of the design structure, that is, the co-operating generators. In  other  words,
              there  are  no restrictions on the description of the design structure: Python's full power can be
              used for that purpose. Also, the design hierarchy can be arbitrarily deep.

       Generator are mapped to Verilog or VHDL constructs
              The converter analyzes the code of each generator and maps it  to  equivalent  constructs  in  the
              target  HDL.  For  Verilog,  it  will  map  generators to always blocks, continuous assignments or
              initial blocks. For VHDL, it will map them to process statements or concurrent signal assignments.

       The module ports are inferred from signal usage
              In MyHDL, the input or output direction  of  ports  is  not  explicitly  declared.  The  converter
              investigates  signal  usage  in  the  design hierarchy to infer whether a signal is used as input,
              output, or as an internal signal.

       Interfaces are convertible
              An interface: an object that has a number of Signal  objects  as  its  attributes.  The  converter
              supports this by name expansion and mangling.

       Function calls are mapped to Verilog or VHDL subprograms
              The converter analyzes function calls and function code. Each function is mapped to an appropriate
              subprogram  in  the  target  HDL:  a function or task in  Verilog, and a function  or procedure in
              VHDL.  In order to support the full power of Python functions, a unique  subprogram  is  generated
              per Python function call.

       If-then-else structures may be mapped to case statements
              Python  does  not  provide  a  case  statement.  However,   the  converter recognizes if-then-else
              structures in which a variable is sequentially compared to items of an enumeration type, and  maps
              such a structure to a Verilog or VHDL case statement with the appropriate synthesis attributes.

       Choice of encoding schemes for enumeration types
              The  enum  function  in  MyHDL  returns  an  enumeration  type.  This function takes an additional
              parameter encoding that specifies the desired encoding in the implementation: binary, one hot,  or
              one cold. The converter generates the appropriate code for the specified encoding.

       RAM memory
              Certain synthesis tools can map Verilog memories or VHDL arrays to RAM structures. To support this
              interesting feature, the converter maps lists of signals to Verilog memories or VHDL arrays.

       ROM memory
              Some  synthesis tools can infer a ROM from a case statement. The converter does the expansion into
              a case statement automatically, based on a higher level description. The ROM access  is  described
              in a single line, by indexing into a tuple of integers.

       Signed arithmetic
              In  MyHDL,  working  with  negative  numbers  is  trivial:  one  just uses an intbv object with an
              appropriate constraint on its values.  In contrast,  both  Verilog  and  VHDL  make  a  difference
              between  an  unsigned  and  a signed representation. To work with negative values, the user has to
              declare a signed variable explicitly. But when signed  and  unsigned  operands  are  mixed  in  an
              expression, things may become tricky.

              In Verilog, when signed and unsigned operands are mixed, all operands are interpreted as unsigned.
              Obviously,  this  leads  to  unexpected results. The designer will have to add sign extensions and
              type casts to solve this.

              In VHDL, mixing signed and unsigned will generally not work. The designer will have to  match  the
              operands manually by adding resizings and type casts.

              In  MyHDL,  these  issues don't exist because intbv objects simply work as (constrained) integers.
              Moreover, the converter automates the cumbersome tasks that are required in Verilog and  VHDL.  It
              uses  signed  or  unsigned  types  based  on  the  value  constraints  of  the  intbv objects, and
              automatically performs the required sign extensions, resizings, and type casts.

       User-defined code
              If desired, the user can bypass the conversion  process  and  describe  user-defined  code  to  be
              inserted instead.

   The convertible subset
   Introduction
       Unsurprisingly,  not  all  MyHDL  code  can be converted.  Although the restrictions are significant, the
       convertible subset is much broader than the RTL synthesis subset which is an industry standard.  In other
       words, MyHDL code written according to the RTL synthesis rules, should always be convertible. However, it
       is also possible to write convertible code for non-synthesizable models or test benches.

       The converter attempts to issue clear error messages when  it  encounters  a  construct  that  cannot  be
       converted.

       Recall  that  any  restrictions only apply to the design after elaboration.  In practice, this means that
       they apply only to the code of the generators, that are the leaf functional blocks in a MyHDL design.

   Coding style
       A natural restriction on convertible code is that it  should  be  written  in  MyHDL  style:  cooperating
       generators, communicating through signals, and with sensitivity specify resume conditions.

       For  pure  modeling,  it  doesn't  matter  how generators are created.  However, in convertible code they
       should be created using one of the MyHDL decorators: instance, always, always_seq, or always_comb.

   Supported types
       The most important restriction regards object types.  Only a limited amount of types  can  be  converted.
       Python  int  and  long  objects are mapped to Verilog or VHDL integers. All other supported types need to
       have a defined bit width. The supported types are the Python bool type, the MyHDL intbv type,  and  MyHDL
       enumeration types returned by function enum.

       intbv  objects  must  be constructed so that a bit width can be inferred.  This can be done by specifying
       minimum and maximum values, e.g. as follows:

          index = intbv(0, min=MIN, max=MAX)

       The Verilog converter supports intbv objects that can take negative values.

       Alternatively, a slice can be taken from an intbv object as follows:

          index = intbv(0)[N:]

       Such as slice returns a new intbv object, with minimum value 0 , and maximum value 2**N.

       In addition to the scalar types described above, the converter also supports a number of tuple  and  list
       based types. The mapping from MyHDL types is summarized in the following table.
                 ┌─────────────────────┬─────────────────────┬───────┬─────────────────────┬────────┐
                 │ MyHDL type          │ VHDL type           │ Notes │ Verilog type        │ Notes  │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ intinteger             │       │ integer             │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ boolstd_logic           │ (1)   │ reg                 │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ intbv with min >= 0unsigned            │ (2)   │ reg                 │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ intbv with  min < 0signed              │ (2)   │ reg signed          │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ enum                │ dedicated           │       │ reg                 │        │
                 │                     │ enumeration type    │       │                     │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ tuple of int        │ mapped    to   case │ (3)   │ mapped   to    case │ (3)    │
                 │                     │ statement           │       │ statement           │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ list of boolarray of std_logic  │       │ reg                 │ (5)    │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ list  of intbv with │ array of unsigned   │ (4)   │ reg                 │ (4)(5) │
                 │ min >= 0            │                     │       │                     │        │
                 ├─────────────────────┼─────────────────────┼───────┼─────────────────────┼────────┤
                 │ list of intbv  with │ array of signed     │ (4)   │ reg signed          │ (4)(5) │
                 │ min < 0             │                     │       │                     │        │
                 └─────────────────────┴─────────────────────┴───────┴─────────────────────┴────────┘

       Notes:

       1. The VHDL std_logic type is defined in the standard VHDL package IEEE.std_logic_1164.

       2. The VHDL unsigned and signed types used are those from the standard VHDL packages IEEE.numeric_std.

       3. A  MyHDL  tuple  of  int  is  used  for ROM inference, and can only be used in a very specific way: an
          indexing operation into the tuple should be the rhs of an assignment.

       4. All list members should have identical value constraints.

       5. Lists are mapped to Verilog memories.

       The table as presented applies to MyHDL variables. The converter also supports  MyHDL  signals  that  use
       bool,  intbv or enum objects as their underlying type. For VHDL, these are mapped to VHDL signals with an
       underlying type as specified in the table above. Verilog doesn't have the signal concept. For Verilog,  a
       MyHDL  signal  is  mapped  to a Verilog reg as in the table above, or to a Verilog wire, depending on the
       signal usage.

       The converter supports MyHDL list of signals provided the underlying signal type is either bool or intbv.
       They may be mapped to a VHDL signal with a VHDL type as specified in the table, or to a  Verilog  memory.
       However, list of signals are not always mapped to a corresponding VHDL or Verilog object.  See Conversion
       of lists of signals for more info.

   Supported statements
       The following is a list of the statements that are supported by the Verilog converter, possibly qualified
       with restrictions or usage notes.

       assert An assert statement in Python looks as follow:

                 assert test_expression

              It can be converted provided test_expression is convertible.

       break

       continue

       def

       for    The  only  supported  iteration  scheme  is  iterating  through  sequences of integers returned by
              built-in function range or MyHDL function downrange.  The optional else clause is not supported.

       if     if, elif, and else clauses are fully supported.

       pass

       print
          A print statement with multiple arguments:

              print arg1, arg2, ...

          is supported. However, there are restrictions on the arguments.  First, they should be of one  of  the
          following forms:

              arg
              formatstring % arg
              formatstring % (arg1, arg2, ...)

          where arg is a bool, int, intbv, enum, or a Signal of these types.

          The  formatstring  contains  ordinary  characters and conversion specifiers as in Python. However, the
          only supported conversion specifiers are %s and %d.  Justification and width  specification  are  thus
          not supported.

          Printing without a newline:

              print arg1 ,

          is not supported.

       raise  This statement is mapped to statements that end the simulation with an error message.

       return

       yield  A yield expression is used to specify a sensitivity list.  The yielded expression can be a Signal,
              a  signal  edge  as  specified  by MyHDL functions Signal.posedge or Signal.negedge, or a tuple of
              signals and edge specifications. It can also be a delay object.

       while  The optional else clause is not supported.

   Supported built-in functions
       The following is a list of the built-in functions that are supported by the converter.

       bool   This function can be used to typecast an object explicitly to its boolean interpretation.

       len    For Signal and intbv objects, function len returns the bit width.

       int    This function can be used to typecast an object explicitly to its integer interpretation.

   Docstrings
       The converter propagates comments under the form of Python docstrings.

       Docstrings are typically used in Python to document certain objects in a standard  way.  Such  "official"
       docstrings  are  put into the converted output at appropriate locations.  The converter supports official
       docstrings for the top level module and for generators.

       Within generators, "nonofficial" docstrings are propagated also. These  are  strings  (triple  quoted  by
       convention) that can occur anywhere between statements.

       Regular  Python  comments  are  ignored by the Python parser, and they are not present in the parse tree.
       Therefore, these are not propagated. With docstrings, you have an elegant way to specify  which  comments
       should be propagated and which not.

   Conversion of lists of signals
       Lists  of  signals  are  useful  for many purposes. For example, they make it easy to create a repetitive
       structure. Another application is the description of memory behavior.

       The converter output is non-hierarchical. That implies that all signals are declared at the top-level  in
       VHDL  or  Verilog  (as  VHDL  signals, or Verilog regs and wires.)  However, some signals that are a list
       member at some level in the MyHDL design hierarchy may be used as a plain signal at a  lower  level.  For
       such  signals,  a choice has to be made whether to declare a Verilog memory or VHDL array, or a number of
       plain signal names.

       If possible, plain signal declarations are preferred, because  Verilog  memories  and  arrays  have  some
       restrictions  in  usage  and  tool support.  This is possible if the list syntax is strictly used outside
       generator code, for example when lists of signals are used to describe structure.

       Conversely, when list syntax is used in some generator, then a Verilog  memory  or  VHDL  array  will  be
       declared. The typical example is the description of RAM memories.

   Conversion of Interfaces
       Complex  designs  often  have  many signals that are passed to different levels of hierarchy.  Typically,
       many signals logically belong together. This can be modelled by an interface: an object that has a number
       of Signal objects as its attributes.  Grouping signals into an interface simplifies  the  code,  improves
       efficiency, and reduces errors.

       The converter supports interface using hierarchical name expansion and name mangling.

   Assignment issues
   Name assignment in Python
       Name  assignment  in  Python  is  a  different  concept than in many other languages.  This point is very
       important for effective modeling in Python, and even more so for synthesizable MyHDL code. Therefore, the
       issues are discussed here explicitly.

       Consider the following name assignments:

          a = 4
          a = ``a string''
          a = False

       In many languages, the meaning would be that an existing variable a gets a number of different values. In
       Python, such a concept of a variable doesn't exist. Instead, assignment merely creates a new binding of a
       name to a certain object, that replaces any previous binding. So in the example, the name a  is  bound  a
       number of different objects in sequence.

       The  converter has to investigate name assignment and usage in MyHDL code, and to map names to Verilog or
       VHDL objects. To achieve that, it tries to infer the type and possibly the bit width of  each  expression
       that is assigned to a name.

       Multiple assignments to the same name can be supported if it can be determined that a consistent type and
       bit  width  is  being  used  in  the  assignments.  This  can  be  done  for boolean expressions, numeric
       expressions, and enumeration type literals.

       In other cases, a single assignment should be used when an object is created.  Subsequent  value  changes
       are  then  achieved  by modification of an existing object.  This technique should be used for Signal and
       intbv objects.

   Signal assignment
       Signal assignment in MyHDL is implemented using attribute assignment to attribute  next.   Value  changes
       are  thus modeled by modification of the existing object. The converter investigates the Signal object to
       infer the type and bit width of the corresponding Verilog or VHDL object.

   intbv objects
       Type intbv is likely to be the workhorse for synthesizable modeling in MyHDL. An intbv  instance  behaves
       like  a  (mutable)  integer  whose  individual bits can be accessed and modified. Also, it is possible to
       constrain its set of values. In addition to error checking, this makes it possible to infer a bit  width,
       which is required for implementation.

       As  noted  before,  it  is  not possible to modify value of an intbv object using name assignment. In the
       following, we will show how it can be done instead.  Consider:

          a = intbv(0)[8:]

       This is an intbv object with initial value 0 and bit width 8. To change its value to 5, we can use  slice
       assignment:

          a[8:] = 5

       The  same  can  be  achieved  by leaving the bit width unspecified, which has the meaning to change "all"
       bits:

          a[:] = 5

       Often the new value will depend on the old one. For example, to increment an  intbv  with  the  technique
       above:

          a[:] = a + 1

       Python  also provides augmented assignment operators, which can be used to implement in-place operations.
       These are supported on intbv objects and by the converter, so that the increment  can  also  be  done  as
       follows:

          a += 1

   Excluding code from conversion
       For  some  tasks,  such as debugging, it may be useful to insert arbitrary Python code that should not be
       converted.

       The converter supports this by ignoring all code that is embedded in a if __debug__ test.  The  value  of
       the __debug__ variable is not taken into account.

   User-defined code
       MyHDL  provides  a  way  to  include  user-defined  code during the conversion process. There are special
       function attributes that are understood by the converter but ignored by the simulator. The attributes are
       verilog_code for Verilog and vhdl_code for VHDL.  They operate like a special return value. When  defined
       in a MyHDL function, the converter will use their value instead of the regular return value. Effectively,
       it will stop converting at that point.

       The  value  of  verilog_code  or vhdl_code should be a Python template string. A template string supports
       $-based substitutions.  The $name notation can be used to refer to the variable names in the  context  of
       the string. The converter will substitute the appropriate values in the string and then insert it instead
       of the regular converted output.

       There is one more issue with user-defined code.  Normally, the converter infers inputs, internal signals,
       and  outputs.  It  also detects undriven and multiple driven signals. To do this, it assumes that signals
       are not driven by default. It then processes the code to find out which signals are driven from where.

       Proper signal usage inference cannot be done with user-defined code. Without user help, this will  result
       in  warnings or errors during the inference process, or in compilation errors from invalid code. The user
       can solve this by setting the driven or read attribute for signals that  are  driven  or  read  from  the
       user-defined  code.   These  attributes  are  False  by default.  The allowed "true" values of the driven
       attribute are True, 'wire' and 'reg'. The latter two values specifies how the user-defined  Verilog  code
       drives the signal in Verilog. To decide which value to use, consider how the signal should be declared in
       Verilog after the user-defined code is inserted.

       For an example of user-defined code, see conv-usage-custom.

   Template transformation
       NOTE:
          This section is only relevant for VHDL.

       There  is  a  difference  between  VHDL  and  Verilog  in the way in which sensitivity to signal edges is
       specified. In Verilog, edge specifiers can be used directly in the sensitivity list. In VHDL, this is not
       possible: only signals can be used in  the  sensitivity  list.  To  check  for  an  edge,  one  uses  the
       rising_edge() or falling_edge() functions in the code.

       MyHDL  follows  the  Verilog  scheme to specify edges in the sensitivity list. Consequently, when mapping
       such code to VHDL, it needs to be transformed to equivalent VHDL. This is an important issue  because  it
       affects all synthesizable templates that infer sequential logic.

       We will illustrate this feature with some examples. This is the MyHDL code for a D flip-flop:

          @always(clk.posedge)
          def logic():
              q.next = d

       It is converted to VHDL as follows:

          DFF_LOGIC: process (clk) is
          begin
              if rising_edge(clk) then
                  q <= d;
              end if;
          end process DFF_LOGIC;

       The  converter  can  handle the more general case. For example, this is MyHDL code for a D flip-flop with
       asynchronous set, asynchronous reset, and preference of set over reset:

          @always(clk.posedge, set.negedge, rst.negedge)
          def logic():
              if set == 0:
                  q.next = 1
              elif rst == 0:
                  q.next = 0
              else:
                  q.next = d

       This is converted to VHDL as follows:

          DFFSR_LOGIC: process (clk, set, rst) is
          begin
              if (set = '0') then
                  q <= '1';
              elsif (rst = '0') then
                  q <= '0';
              elsif rising_edge(clk) then
                  q <= d;
              end if;
          end process DFFSR_LOGIC;

       All cases with practical utility can be handled in this way. However, there are other cases  that  cannot
       be transformed to equivalent VHDL. The converter will detect those cases and give an error.

   Conversion output verification by co-simulation
       NOTE:
          This section is only relevant for Verilog.

       To  verify  the  converted  Verilog  output,  co-simulation  can  be  used. To make this task easier, the
       converter also generates a test bench that makes it possible to simulate the  Verilog  design  using  the
       Verilog  co-simulation  interface.  This  permits one to verify the Verilog code with the same test bench
       used for the MyHDL code.

   Conversion of test benches
       After conversion, we obviously want to verify that the VHDL or Verilog code works correctly. For Verilog,
       we can use co-simulation as  discussed  earlier.  However,  for  VHDL,  co-simulation  is  currently  not
       supported.

       An  alternative is to convert the test bench itself, so that both test bench and design can be run in the
       HDL simulator. Of course, this is not a fully general solution, as there are important constraints on the
       kind of code that can be converted.  Thus, the question is whether the conversion restrictions permit one
       to develop sufficiently complex test benches. In this section, we present some insights about this.

       The most important restrictions regard the types that can be used, as discussed earlier in this  chapter.
       However,  the  "convertible  subset"  is  wider  than the "synthesis subset". We will present a number of
       non-synthesizable feature that are of interest for test benches.

       the while loop
              while loops can be used for high-level control structures.

       the raise statement
              A raise statement can stop the simulation on an error condition.

       delay objects
              Delay modeling is essential for test benches.

       the print statement
              print statements can be used for simple debugging.

       the assert statement.
              Originally, assert statements were only intended to insert debugging assertions in code. Recently,
              there is a tendency to use them to  write  self-checking  unit  tests,  controlled  by  unit  test
              frameworks  such  as  py.test.  In particular, they are a powerful way to write self-checking test
              benches for MyHDL designs. As assert statements are convertible, a whole unit test suite in  MyHDL
              can be converted to an equivalent test suite in Verilog and VHDL.

       Additionally,  the  same  techniques  as  for  synthesizable  code  can  be used to master complexity. In
       particular, any code outside generators is executed during elaboration, and therefore not  considered  in
       the  conversion  process.  This  feature  can  for  example  be used for complex calculations that set up
       constants or expected results.  Furthermore, a tuple of ints can be used to hold a table of  values  that
       will be mapped to a case statement in Verilog and VHDL.

   Methodology notes
   Simulate first
       In  the  Python  philosophy,  the  run-time rules. The Python compiler doesn't attempt to detect a lot of
       errors beyond syntax errors, which given Python's ultra-dynamic nature would be an almost impossible task
       anyway. To verify a Python program, one should run it, preferably  using  unit  testing  to  verify  each
       feature.

       The  same  philosophy  should  be  used  when  converting  a  MyHDL description to Verilog: make sure the
       simulation runs fine first. Although the converter checks many things and attempts to issue  clear  error
       messages, there is no guarantee that it does a meaningful job unless the simulation runs fine.

   Handling hierarchy
       Recall  that  conversion  occurs  after  elaboration.  A  consequence  is  that  the  converted output is
       non-hierarchical. In many cases, this is not an issue. The purpose of conversion is  to  provide  a  path
       into  a  traditional  design  flow  by  using Verilog and VHDL as a "back-end" format. Hierarchy is quite
       relevant to humans, but much less so to tools.

       However, in some cases hierarchy is desirable. For example, if you convert a test bench you may prefer to
       keep its code separate from the design under test. In other words, conversion should stop at  the  design
       under test instance, and insert an instantiation instead.

       There  is  a  workaround  to accomplish this with a small amount of additional work. The workaround is to
       define user-defined code consisting of an instantiation  of  the  design  under  test.  As  discussed  in
       User-defined  code, when the converter sees the hook it will stop converting and insert the instantiation
       instead. Of course, you will want to convert the design under test itself also. Therefore, you should use
       a flag that controls whether the hook is defined or not and set it according to the desired conversion.

   Known issues
       Verilog and VHDL integers are 32 bit wide
              Usually, Verilog and VHDL integers are 32 bit wide. In contrast, Python is moving toward  integers
              with  undefined width. Python int and long variables are mapped to Verilog integers; so for values
              wider than 32 bit this mapping is incorrect.

       Synthesis pragmas are specified as Verilog comments.
              The recommended way to specify synthesis pragmas in Verilog is through attribute  lists.  However,
              the  Icarus  simulator  doesn't  support  them  for  case statements (to specify parallel_case and
              full_case pragmas). Therefore, the old but deprecated  method  of  synthesis  pragmas  in  Verilog
              comments is still used.

       Inconsistent place of the sensitivity list inferred from always_comb.
              The  semantics  of always_comb, both in Verilog and MyHDL, is to have an implicit sensitivity list
              at the end of  the  code.  However,  this  may  not  be  synthesizable.  Therefore,  the  inferred
              sensitivity  list  is  put at the top of the corresponding always block or process. This may cause
              inconsistent behavior at the start of the simulation. The workaround is to create events  at  time
              0.

   Conversion examples
   Introduction
       In  this  chapter, we will demonstrate the conversion process with a number of examples. For the concepts
       of MyHDL conversion, read the companion chapter conv.

   A small sequential design
       Consider the following MyHDL code for an incrementer block:

       This design can be converted to Verilog and VHDL. The first step is to elaborate it, just as  we  do  for
       simulation. Then we can use the convert method on the elaborated instance.

       For  flexibility,  we  wrap  the  conversion  in  a  convert_inc function.  inc_1 is an elaborated design
       instance that provides the conversion method.

       The conversion to Verilog generates an equivalent Verilog module in file inc.v. The Verilog code looks as
       follows:

       The converter infers a proper Verilog module interface and maps the MyHDL generator to a  Verilog  always
       block.

       Similarly, the conversion to VHDL generates a file inc.vhd with  the following content:

       The MyHDL generator is mapped to a VHDL process in this case.

       Note  that  the  VHDL  file refers to a VHDL package called pck_myhdl_<version>.  This package contains a
       number of convenience functions that make the conversion easier.

       Note also the use of an inout in the interface.  This is not recommended VHDL design practice, but it  is
       required  here to have a valid VHDL design that matches the behavior of the MyHDL design. As this is only
       an issue for ports and as the converter output is non-hierarchical, the issue is not very common and  has
       an easy workaround.

   A small combinatorial design
       The  second  example is a small combinatorial design, more specifically the binary to Gray code converter
       from previous chapters:

       As before, you can create an instance and convert to Verilog and VHDL as follows:

       The generated Verilog code looks as follows:

       The generated VHDL code looks as follows:

   A hierarchical design
       The converter can handle designs with an arbitrarily deep hierarchy.

       For example, suppose we want to design an incrementer with Gray code  output.   Using  the  designs  from
       previous sections, we can proceed as follows:

       According  to  Gray code properties, only a single bit will change in consecutive values. However, as the
       bin2gray module is combinatorial, the  output  bits  may  have  transient  glitches,  which  may  not  be
       desirable. To solve this, let's create an additional level of hierarchy and add an output register to the
       design.  (This  will  create  an additional latency of a clock cycle, which may not be acceptable, but we
       will ignore that here.)

       We can convert this hierarchical design as follows:

       The Verilog output code looks as follows:

       The VHDL output code looks as follows:

       Note that the output is a flat "net list of blocks", and that hierarchical signal names are generated  as
       necessary.

   Optimizations for finite state machines
       As often in hardware design, finite state machines deserve special attention.

       In Verilog and VHDL, finite state machines are typically described using case statements.  Python doesn't
       have  a  case statement, but the converter recognizes particular if-then-else structures and maps them to
       case statements. This  optimization  occurs  when  a  variable  whose  type  is  an  enumerated  type  is
       sequentially  tested  against  enumeration  items  in  an  if-then-else structure.  Also, the appropriate
       synthesis pragmas for efficient synthesis are generated in the Verilog code.

       As a further optimization, function enum was enhanced to support alternative encoding schemes  elegantly,
       using an additional parameter encoding. For example:

          t_State = enum('SEARCH', 'CONFIRM', 'SYNC', encoding='one_hot')

       The  default  encoding  is 'binary'; the other possibilities are 'one_hot' and 'one_cold'. This parameter
       only affects the conversion output, not the behavior of the type.  The generated Verilog  code  for  case
       statements is optimized for an efficient implementation according to the encoding. Note that in contrast,
       a Verilog designer has to make nontrivial code changes to implement a different encoding scheme.

       As  an  example,  consider  the following finite state machine, whose state variable uses the enumeration
       type defined above:

          ACTIVE_LOW = bool(0)
          FRAME_SIZE = 8
          t_State = enum('SEARCH', 'CONFIRM', 'SYNC', encoding="one_hot")

          def FramerCtrl(SOF, state, syncFlag, clk, reset_n):

              """ Framing control FSM.

              SOF -- start-of-frame output bit
              state -- FramerState output
              syncFlag -- sync pattern found indication input
              clk -- clock input
              reset_n -- active low reset

              """

              index = Signal(intbv(0)[8:]) # position in frame

              @always(clk.posedge, reset_n.negedge)
              def FSM():
                  if reset_n == ACTIVE_LOW:
                      SOF.next = 0
                      index.next = 0
                      state.next = t_State.SEARCH
                  else:
                      index.next = (index + 1) % FRAME_SIZE
                      SOF.next = 0
                      if state == t_State.SEARCH:
                          index.next = 1
                          if syncFlag:
                              state.next = t_State.CONFIRM
                      elif state == t_State.CONFIRM:
                          if index == 0:
                              if syncFlag:
                                  state.next = t_State.SYNC
                              else:
                                  state.next = t_State.SEARCH
                      elif state == t_State.SYNC:
                          if index == 0:
                              if not syncFlag:
                                  state.next = t_State.SEARCH
                          SOF.next = (index == FRAME_SIZE-1)
                      else:
                          raise ValueError("Undefined state")

              return FSM

       The conversion is done as before:

          SOF = Signal(bool(0))
          syncFlag = Signal(bool(0))
          clk = Signal(bool(0))
          reset_n = Signal(bool(1))
          state = Signal(t_State.SEARCH)
          toVerilog(FramerCtrl, SOF, state, syncFlag, clk, reset_n)
          toVHDL(FramerCtrl, SOF, state, syncFlag, clk, reset_n)

       The Verilog output looks as follows:

          module FramerCtrl (
              SOF,
              state,
              syncFlag,
              clk,
              reset_n
          );

          output SOF;
          reg SOF;
          output [2:0] state;
          reg [2:0] state;
          input syncFlag;
          input clk;
          input reset_n;

          reg [7:0] index;

          always @(posedge clk, negedge reset_n) begin: FRAMERCTRL_FSM
              if ((reset_n == 0)) begin
                  SOF <= 0;
                  index <= 0;
                  state <= 3'b001;
              end
              else begin
                  index <= ((index + 1) % 8);
                  SOF <= 0;
                  // synthesis parallel_case full_case
                  casez (state)
                      3'b??1: begin
                          index <= 1;
                          if (syncFlag) begin
                              state <= 3'b010;
                          end
                      end
                      3'b?1?: begin
                          if ((index == 0)) begin
                              if (syncFlag) begin
                                  state <= 3'b100;
                              end
                              else begin
                                  state <= 3'b001;
                              end
                          end
                      end
                      3'b1??: begin
                          if ((index == 0)) begin
                              if ((!syncFlag)) begin
                                  state <= 3'b001;
                              end
                          end
                          SOF <= (index == (8 - 1));
                      end
                      default: begin
                          $finish;
                      end
                  endcase
              end
          end

          endmodule

       The VHDL output looks as follows:

          package pck_FramerCtrl is

              type t_enum_t_State_1 is (
              SEARCH,
              CONFIRM,
              SYNC
          );
          attribute enum_encoding of t_enum_t_State_1: type is "001 010 100";

          end package pck_FramerCtrl;

          library IEEE;
          use IEEE.std_logic_1164.all;
          use IEEE.numeric_std.all;
          use std.textio.all;

          use work.pck_myhdl_06.all;

          use work.pck_FramerCtrl.all;

          entity FramerCtrl is
              port (
                  SOF: out std_logic;
                  state: inout t_enum_t_State_1;
                  syncFlag: in std_logic;
                  clk: in std_logic;
                  reset_n: in std_logic
              );
          end entity FramerCtrl;

          architecture MyHDL of FramerCtrl is

          signal index: unsigned(7 downto 0);

          begin

          FRAMERCTRL_FSM: process (clk, reset_n) is
          begin
              if (reset_n = '0') then
                  SOF <= '0';
                  index <= "00000000";
                  state <= SEARCH;
              elsif rising_edge(clk) then
                  index <= ((index + 1) mod 8);
                  SOF <= '0';
                  case state is
                      when SEARCH =>
                          index <= "00000001";
                          if to_boolean(syncFlag) then
                              state <= CONFIRM;
                          end if;
                      when CONFIRM =>
                          if (index = 0) then
                              if to_boolean(syncFlag) then
                                  state <= SYNC;
                              else
                                  state <= SEARCH;
                              end if;
                          end if;
                      when SYNC =>
                          if (index = 0) then
                              if (not to_boolean(syncFlag)) then
                                  state <= SEARCH;
                              end if;
                          end if;
                          SOF <= to_std_logic(signed(resize(index, 9)) = (8 - 1));
                      when others =>
                          assert False report "End of Simulation" severity Failure;
                  end case;
              end if;
          end process FRAMERCTRL_FSM;

          end architecture MyHDL;

   RAM inference
       Certain synthesis tools can infer RAM structures. To support this feature, the converter  maps  lists  of
       signals in MyHDL to Verilog memories and VHDL arrays.

       The following MyHDL example is a ram model that uses a list of signals to model the internal memory.

          def RAM(dout, din, addr, we, clk, depth=128):
              """  Ram model """

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

              @always(clk.posedge)
              def write():
                  if we:
                      mem[addr].next = din

              @always_comb
              def read():
                  dout.next = mem[addr]

              return write, read

       With the appropriate signal definitions for the interface ports, it is converted to the following Verilog
       code. Note how the list of signals mem is mapped to a Verilog memory.

          module ram (
              dout,
              din,
              addr,
              we,
              clk
          );

          output [7:0] dout;
          wire [7:0] dout;
          input [7:0] din;
          input [6:0] addr;
          input we;
          input clk;

          reg [7:0] mem [0:128-1];

          always @(posedge clk) begin: RAM_1_WRITE
              if (we) begin
                  mem[addr] <= din;
              end
          end

          assign dout = mem[addr];

          endmodule

       In VHDL, the list of MyHDL signals is modeled as a VHDL array signal:

          library IEEE;
          use IEEE.std_logic_1164.all;
          use IEEE.numeric_std.all;

          use work.pck_myhdl_06.all;

          entity ram is
              port (
                  dout: out unsigned(7 downto 0);
                  din: in unsigned(7 downto 0);
                  addr: in unsigned(6 downto 0);
                  we: in std_logic;
                  clk: in std_logic
              );
          end entity ram;

          architecture MyHDL of ram is

          type t_array_mem is array(0 to 128-1) of unsigned(7 downto 0);
          signal mem: t_array_mem;

          begin

          RAM_WRITE: process (clk) is
          begin
              if rising_edge(clk) then
                  if to_boolean(we) then
                      mem(to_integer(addr)) <= din;
                  end if;
              end if;
          end process RAM_WRITE;

          dout <= mem(to_integer(addr));

          end architecture MyHDL;

   ROM inference
       Some  synthesis tools can infer a ROM memory from a case statement. The Verilog converter can perform the
       expansion into a case statement automatically, based on a higher level description.  The  ROM  access  is
       described  in  a  single line, by indexing into a tuple of integers. The tuple can be described manually,
       but also by programmatical means. Note that a tuple is used instead of a list  to  stress  the  read-only
       character of the memory.

       The following example illustrates this functionality. ROM access is described as follows:

          def rom(dout, addr, CONTENT):

              @always_comb
              def read():
                  dout.next = CONTENT[int(addr)]

              return read

       The  ROM content is described as a tuple of integers. When the ROM content is defined, the conversion can
       be performed:

          CONTENT = (17, 134, 52, 9)
          dout = Signal(intbv(0)[8:])
          addr = Signal(intbv(0)[4:])

          toVerilog(rom, dout, addr, CONTENT)
          toVHDL(rom, dout, addr, CONTENT)

       The Verilog output code is as follows:

          module rom (
              dout,
              addr
          );

          output [7:0] dout;
          reg [7:0] dout;
          input [3:0] addr;

          always @(addr) begin: ROM_READ
              // synthesis parallel_case full_case
              case (addr)
                  0: dout <= 17;
                  1: dout <= 134;
                  2: dout <= 52;
                  default: dout <= 9;
              endcase
          end

          endmodule

       The VHDL output code is as follows:

          library IEEE;
          use IEEE.std_logic_1164.all;
          use IEEE.numeric_std.all;
          use std.textio.all;

          use work.pck_myhdl_06.all;

          entity rom is
              port (
                  dout: out unsigned(7 downto 0);
                  addr: in unsigned(3 downto 0)
              );
          end entity rom;

          architecture MyHDL of rom is

          begin

          ROM_READ: process (addr) is
          begin
              case to_integer(addr) is
                  when 0 => dout <= "00010001";
                  when 1 => dout <= "10000110";
                  when 2 => dout <= "00110100";
                  when others => dout <= "00001001";
              end case;
          end process ROM_READ;

          end architecture MyHDL;

   User-defined code
       MyHDL provides a way to include user-defined code  during  the  conversion  process,  using  the  special
       function attributes vhdl_code and verilog_code.

       For example:

          def inc_comb(nextCount, count, n):

              @always(count)
              def logic():
                  # do nothing here
                  pass

              nextCount.driven = "wire"

              return logic

          inc_comb.verilog_code =\
          """
          assign $nextCount = ($count + 1) % $n;
          """

          inc_comb.vhdl_code =\
          """
          $nextCount <= ($count + 1) mod $n;
          """

       The converted code looks as follows in Verilog:

          module inc_comb (
              nextCount,
              count
          );

          output [7:0] nextCount;
          wire [7:0] nextCount;
          input [7:0] count;

          assign nextCount = (count + 1) % 256;

          endmodule

       and as follows in VHDL:

          library IEEE;
          use IEEE.std_logic_1164.all;
          use IEEE.numeric_std.all;

          use work.pck_myhdl_06.all;

          entity inc_comb is
              port (
                  nextCount: out unsigned(7 downto 0);
                  count: in unsigned(7 downto 0)
              );
          end entity inc_comb;

          architecture MyHDL of inc_comb is

          begin

          nextCount <= (count + 1) mod 256;

          end architecture MyHDL;

       In  this  example,  conversion of the inc_comb function is bypassed and the user-defined code is inserted
       instead. The user-defined code is a Python template string that can refer to signals  and  parameters  in
       the  MyHDL  context through $-based substitutions.  During conversion, the appropriate hierarchical names
       and parameter values will be substituted.

       The MyHDL code contains the following assignment:

          nextCount.driven = "wire"

       This specifies that the nextCount signal is driven as a Verilog wire from this module.

       For more info about user-defined code, see conv-custom.

   Reference
       MyHDL is implemented as a Python package called myhdl.  This  chapter  describes  the  objects  that  are
       exported by this package.

   Simulation
   The Simulation class
       class Simulation(arg[, arg ...])
              Class  to  construct  a  new  simulation.  Each argument should be a MyHDL instance.  In MyHDL, an
              instance is recursively defined as being either a sequence of instances, or a MyHDL generator,  or
              a  Cosimulation  object.  See  section  MyHDL generators and trigger objects for the definition of
              MyHDL generators and their interaction with a Simulation object.  See  Section  Co-simulation  for
              the  Cosimulation  object.   At  most  one  Cosimulation  object  can  be  passed  to a Simulation
              constructor.

       A Simulation object has the following method:

       Simulation.run([duration])
              Run the simulation forever (by default) or for a specified duration.

       Simulation.quit()
              Quit the simulation after it has run for a specified duration. The method should  be  called  (the
              simulation  instance  must  be  quit) before another simulation instance is created. The method is
              called by default when the simulation is run forever.

   Simulation support functions
       now()  Returns the current simulation time.

       exception StopSimulation
              Base exception that is caught by the Simulation.run() method to stop a simulation.

   Waveform tracing
       traceSignals(func [, *args] [, **kwargs])
              Enables signal tracing to a VCD file for waveform viewing. func is  a  function  that  returns  an
              instance.  traceSignals calls func under its control and passes *args and **kwargs to the call. In
              this way, it finds the hierarchy and the signals to be traced.

              The return value is the same as  would  be  returned  by  the  call  func(*args,  **kwargs).   The
              top-level  instance name and the basename of the VCD output filename is func.func_name by default.
              If the VCD file exists already, it will be moved to a backup file by attaching a timestamp to  it,
              before creating the new file.

              The traceSignals callable has the following attribute:

              name   This attribute is used to overwrite the default top-level instance name and the basename of
                     the VCD output filename.

              directory
                     This attribute is used to set the directory to which VCD files are written. By default, the
                     current working directory is used.

              filename
                     This  attribute is used to set the filename to which VCD files are written. By default, the
                     name attribbute is used.

              timescale
                     This attribute is used to set the timescale corresponding to unit steps, according  to  the
                     VCD format. The assigned value should be a string.  The default timescale is "1ns".

   Modeling
   The block decorator
       block()
              The   block   decorator   enables   a  method-based  API  which  is  more  consistent,  simplifies
              implementation, and reduces the size of the myhdl namespace.

              The methods work on block instances, created by  calling  a  function  decorated  with  the  block
              decorator:

                 @block
                 def myblock(<ports>):
                 ...
                 return <instances>

                 inst = myblock(<port-associations>)
                 # inst supports the methods of the block instance API

       The API on a block instance looks as follows:

       <block_instance>.run_sim(duration=None)
              Run a simulation "forever" (default) or for a specified duration.

       <block_instance>.config_sim(backend='myhdl', trace=False)
              Optional simulation configuration:

              backend: Defaults to 'myhdl

              trace: Enable waveform tracing, default False.

       <block_instance>.quit_sim()
              Quit  an  active simulation. This is method is currently required because only a single simulation
              can be active.

       <block_instance>.convert(hdl='Verilog', **kwargs)
              Converts MyHDL code to a target HDL.

              hdl: 'VHDL' or 'Verilog'. Defaults to Verilog.

              Supported keyword arguments:

              path: Destination folder. Defaults to current working dir.

              name: Module and output file name. Defaults to self.mod.__name__.

              trace: Whether the testbench should dump all signal waveforms. Defaults to False.

              testbench: Verilog only. Specifies whether a testbench should be created.  Defaults to True.

              timescale: timescale parameter. Defaults to '1ns/10ps'. Verilog only.

       <block_instance>.verify_convert()
              Verify conversion output, by comparing target HDL simulation log with MyHDL simulation log.

       <block_instance>.analyze_convert()
              Analyze conversion output by compilation with target HDL compiler.

   Signals
   The SignalType type
       class SignalType
              This type is the abstract base type of all signals. It is not used to construct  signals,  but  it
              can be used to check whether an object is a signal.

   Regular signals
       class Signal([val=None] [, delay=0])
              This  class  is  used  to construct a new signal and to initialize its value to val. Optionally, a
              delay can be specified.

              A Signal object has the following attributes:

                 posedge
                        Attribute that represents the positive edge of a  signal,  to  be  used  in  sensitivity
                        lists.

                 negedge
                        Attribute  that  represents  the  negative  edge  of a signal, to be used in sensitivity
                        lists.

                 next   Read-write attribute that represents the next value of the signal.

                 val    Read-only attribute that represents the current value of the signal.

                        This attribute is always  available  to  access  the  current  value;  however  in  many
                        practical  case  it  will  not  be  needed.  Whenever  there is no ambiguity, the Signal
                        object's current value is used implicitly. In particular, all Python's standard numeric,
                        bit-wise, logical and comparison  operators  are  implemented  on  a  Signal  object  by
                        delegating  to its current value. The exception is augmented assignment. These operators
                        are not implemented as they would break the rule that the  current  value  should  be  a
                        read-only attribute. In addition, when a Signal object is assigned to the next attribute
                        of another Signal object, its current value is assigned instead.

                 min    Read-only  attribute  that is the minimum value (inclusive) of a numeric signal, or None
                        for no minimum.

                 max    Read-only attribute that is the maximum value (exclusive) of a numeric signal,  or  None
                        for no  maximum.

                 driven Writable attribute that can be used to indicate that the signal is supposed to be driven
                        from the MyHDL code, and possibly how it should be declared in Verilog after conversion.
                        The allowed values are 'reg', 'wire', True and False.

                        This  attribute is useful when the  converter cannot infer automatically whether and how
                        a signal is driven. This occurs when the signal is driven from user-defined code.  'reg'
                        and 'wire' are "true" values that permit finer control for the Verilog case.

                 read   Writable boolean attribute that can be used to indicate that the signal is read.

                        This  attribute is useful when the converter cannot infer automatically whether a signal
                        is read. This occurs when the signal is read from user-defined code.

              A Signal object also has a call interface:

                 __call__(left[, right=None])
                        This method returns a _SliceSignal shadow signal.

       class ResetSignal(val, active, isasync)
              This Signal subclass defines reset signals. val, active, and isasync are mandatory arguments.  val
              is a boolean value that specifies the initial value, active is a boolean value that specifies  the
              active  level.   isasync is a boolean value that specifies the reset style: asynchronous (True) or
              synchronous (False).

              This class should be used in conjunction with the always_seq decorator.

   Shadow signals
       class _SliceSignal(sig, left[, right=None])
              This class implements read-only structural slicing and indexing. It creates a new shadow signal of
              the slice or index of the parent signal sig. If the right parameter is omitted, you  get  indexing
              instead  of  slicing.   Parameters  left   and  right have the usual meaning for slice indices: in
              particular, left is non-inclusive but right is inclusive. sig should be  appropriate  for  slicing
              and indexing, which means it should be based on intbv in practice.

              The  class constructor is not intended to be used explicitly. Instead, use the call interface of a
              regular signal.The following calls are equivalent:

                 sl = _SliceSignal(sig, left, right)

                 sl = sig(left, right)

       class ConcatSignal(*args)
              This class creates a new shadow signal of the concatenation of its arguments.

              You can pass an arbitrary number of  arguments  to  the  constructor.   The  arguments  should  be
              bit-oriented  with  a  defined  number of bits.  The following argument types are supported: intbv
              objects with a defined bit width, bool objects, signals of the previous objects, and bit strings.

              The new signal follows the value changes of the signal arguments.  The  non-signal  arguments  are
              used to define constant values in the concatenation.

       class TristateSignal(val)
              This class is used to construct a new tristate signal. The underlying type is specified by the val
              parameter.   It  is a Signal subclass and has the usual attributes, with one exception: it doesn't
              support the next attribute. Consequently, direct signal assignment to a  tristate  signal  is  not
              supported.   The  initial  value  is  the tristate value None.  The current value of a tristate is
              determined by resolving the values from its drivers. When exactly one driver  value  is  different
              from  None,  that  is the resolved value; otherwise it is None. When more than one driver value is
              different from None, a contention warning is issued.

              This class has the following method:

              driver()
                     Returns a new driver to the tristate signal. It is initialized to None.  A driver object is
                     an instance of a special SignalType subclass. In particular, its next attribute can be used
                     to assign a new value to it.

   MyHDL generators and trigger objects
       MyHDL  generators  are  standard  Python  generators  with  specialized  yield  statements.  In  hardware
       description  languages,  the  equivalent  statements are called  sensitivity lists. The general format of
       yield statements in in MyHDL generators is:

       yield clause [, clause ...]

       When a generator executes a yield statement, its execution is suspended at that point. At the same  time,
       each  clause  is a trigger object which defines the condition upon which the generator should be resumed.
       However, per invocation of a yield statement, the generator  resumes  exactly  once,  regardless  of  the
       number of clauses. This happens on the first trigger that occurs.

       In this section, the trigger objects and their functionality will be described.

       Some MyHDL objects that are described elsewhere can directly be used as trigger objects. In particular, a
       Signal can be used as a trigger object. Whenever a signal changes value, the generator resumes. Likewise,
       the  objects  referred to by the signal attributes posedge and negedge are trigger objects. The generator
       resumes on the occurrence of a positive or a negative edge on the signal, respectively.  An  edge  occurs
       when  there  is a change from false to true (positive) or vice versa (negative). For the full description
       of the Signal class and its attributes, see section Signals.

       Furthermore, MyHDL generators can be used as clauses in yield statements.  Such a  generator  is  forked,
       and  starts  operating  immediately,  while the original generator waits for it to complete. The original
       generator resumes when the forked generator returns.

       In addition, the following functions return trigger objects:

       delay(t)
              Return a trigger object that specifies that the generator should resume after a delay t.

       join(arg[, arg ...])
              Join a number of trigger objects together and return a joined trigger object.  The effect is  that
              the joined trigger object will trigger when all of its arguments have triggered.

       Finally,  as  a  special  case,  the  Python  None  object can be present in a yield statement. It is the
       do-nothing trigger object. The generator immediately resumes, as if no yield statement were present. This
       can be useful if the yield statement also has generator clauses: those generators are forked,  while  the
       original generator resumes immediately.

   Decorator functions to create generators
       MyHDL  defines  a  number  of  decorator  functions,  that make it easier to create generators from local
       generator functions.

       instance()
              The instance decorator is the most general decorator.  It automatically  creates  a  generator  by
              calling the decorated generator function.

              It is used as follows:

                 def top(...):
                     ...
                     @instance
                     def inst():
                         <generator body>
                     ...
                     return inst, ...

              This is equivalent to:

                 def top(...):
                     ...
                     def _gen_func():
                         <generator body>
                     ...
                     inst = _gen_func()
                     ...
                     return inst, ...

       always(arg[, *args])
              The  always  decorator is a specialized decorator that targets a widely used coding pattern. It is
              used as follows:

                 def top(...):
                     ...
                     @always(event1, event2, ...)
                     def inst()
                         <body>
                     ...
                     return inst, ...

              This is equivalent to the following:

                 def top(...):
                     ...
                     def _func():
                         <body>

                     def _gen_func()
                         while True:
                             yield event1, event2, ...
                             _func()
                     ...
                     inst = _gen_func()
                     ...
                     return inst, ...

              The argument list of the decorator  corresponds  to  the  sensitivity  list.  Only  signals,  edge
              specifiers, or delay objects are allowed. The decorated function should be a classic function.

       always_comb()
              The always_comb decorator is used to describe combinatorial logic.

                 def top(...):
                     ...
                     @always_comb
                     def comb_inst():
                         <combinatorial body>
                     ...
                     return comb_inst, ...

              The  always_comb  decorator  infers  the  inputs  of the combinatorial logic and the corresponding
              sensitivity list automatically. The decorated function should be a classic function.

       always_seq(edge, reset)
              The always_seq decorator is used to describe sequential (clocked) logic.

              The edge parameter should be a clock edge (clock.posedge or clock.negedge).  The  reset  parameter
              should a ResetSignal object.

   MyHDL data types
       MyHDL defines a number of data types that are useful for hardware description.

   The intbv class
       class intbv([val=0] [, min=None] [, max=None])
              This  class  represents  int-like  objects with some additional features that make it suitable for
              hardware design.

              The val argument can be an int, a long, an intbv or a bit string  (a  string  with  only  '0's  or
              '1's).  For  a bit string argument, the value is calculated as in int(bitstring, 2).  The optional
              min and max arguments can be used to specify the minimum and maximum value of the intbv object. As
              in standard Python practice for ranges, the minimum value is inclusive and the  maximum  value  is
              exclusive.

              The minimum and maximum values of an intbv object are available as attributes:

              min    Read-only  attribute  that  is  the  minimum  value (inclusive) of an intbv, or None for no
                     minimum.

              max    Read-only attribute that is the maximum value (exclusive) of  an  intbv,  or  None  for  no
                     maximum.

              signed()
                     Interprets  the  msb  bit  as  as sign bit and extends it into the higher-order bits of the
                     underlying object value. The msb bit is the  highest-order  bit  within  the  object's  bit
                     width.

              Return type
                     integer

       Unlike int objects, intbv objects are mutable; this is also the reason for their existence. Mutability is
       needed to support assignment to indexes and slices, as is common in hardware design. For the same reason,
       intbv  is not a subclass from int, even though int provides most of the desired functionality. (It is not
       possible to derive a mutable subtype from an immutable base type.)

       An intbv object supports the same comparison, numeric, bitwise, logical, and conversion operations as int
       objects.  See  http://www.python.org/doc/current/lib/typesnumeric.html  for  more  information  on   such
       operations.  In  all  binary operations, intbv objects can work together with int objects. For mixed-type
       numeric operations, the result type is an int or a long. For mixed-type bitwise  operations,  the  result
       type is an intbv.

       In  addition, intbv supports a number of sequence operators.  In particular, the len function returns the
       object's bit width. Furthermore, intbv objects support indexing and slicing operations:
                               ┌─────────────┬──────────────────────────────┬────────┐
                               │ Operation   │ Result                       │ Notes  │
                               ├─────────────┼──────────────────────────────┼────────┤
                               │ bv[i]       │ item i of bv                 │ (1)    │
                               ├─────────────┼──────────────────────────────┼────────┤
                               │ bv[i] = x   │ item i of bv is replaced  by │ (1)    │
                               │             │ x                            │        │
                               ├─────────────┼──────────────────────────────┼────────┤
                               │ bv[i:j]     │ slice of bv from i downto j  │ (2)(3) │
                               ├─────────────┼──────────────────────────────┼────────┤
                               │ bv[i:j] = t │ slice  of bv from i downto j │ (2)(4) │
                               │             │ is replaced by t             │        │
                               └─────────────┴──────────────────────────────┴────────┘

       1. Indexing follows the most common hardware design conventions: the lsb bit is the rightmost bit, and it
          has index 0. This has the following desirable property: if the intbv value is decomposed as a  sum  of
          powers of 2, the bit with index i corresponds to the term 2**i.

       2. In  contrast  to  standard  Python  sequencing  conventions,  slicing  range  are  downward. This is a
          consequence of the indexing convention, combined with the common convention that the most  significant
          digits  of  a number are the leftmost ones. The Python convention of half-open ranges is followed: the
          bit with the highest index is not included. However, it is the leftmost  bit  in  this  case.   As  in
          standard  Python,  this  takes  care  of one-off issues in many practical cases: in particular, bv[i:]
          returns i bits; bv[i:j] has i-j bits.  When the low index j is omitted, it defaults  to  0.  When  the
          high index i is omitted, it means "all" higher order bits.

       3. The  object returned from a slicing access operation is always a positive intbv; higher order bits are
          implicitly assumed to be zero. The bit width is implicitly stored in the return object, so that it can
          be used in concatenations and as an iterator. In addition,  for  a  bit  width  w,  the  min  and  max
          attributes are implicitly set to 0 and 2**w, respectively.

       4. When setting a slice to a value, it is checked whether the slice is wide enough.

       In  addition,  an intbv object supports the iterator protocol. This makes it possible to iterate over all
       its bits, from the high index to index 0. This is only possible for intbv  objects  with  a  defined  bit
       width.

   The modbv class
       class modbv([val=0] [, min=None] [, max=None])
              The modbv class implements modular bit vector types.

              It  is  implemented  as  a  subclass of intbv and supports the same parameters and operators.  The
              difference is in the handling of the min and max boundaries.  Instead  of  throwing  an  exception
              when  those  constraints  are  exceeded,  the value of modbv objects wraps around according to the
              following formula:

                 val = (val - min) % (max - min) + min

              This formula is a generalization  of  modulo  wrap-around  behavior  that  is  often  useful  when
              describing hardware system behavior.

   The enum factory function
       enum(arg [, arg ...] [, encoding='binary'])
              Returns an enumeration type.

              The  arguments  should be string literals that represent the desired names of the enumeration type
              attributes.  The returned type should be assigned to a type name.  For example:

                 t_EnumType = enum('ATTR_NAME_1', 'ATTR_NAME_2', ...)

              The enumeration type identifiers are available as  attributes  of  the  type  name,  for  example:
              t_EnumType.ATTR_NAME_1

              The  optional  keyword argument encoding specifies the encoding scheme used in Verilog output. The
              available encodings are 'binary', 'one_hot', and 'one_cold'.

   Modeling support functions
       MyHDL defines a number of additional support functions that are useful for hardware description.

   bin
       bin(num[, width])
              Returns a bit string representation. If the optional width is provided, and if it is  larger  than
              the width of the default representation, the bit string is padded with the sign bit.

              This  function  complements  the standard Python conversion functions hex and oct. A binary string
              representation is often useful in hardware design.

              Return type
                     string

   concat
       concat(base[, arg ...])
              Returns an intbv object formed by concatenating the arguments.

              The following argument types are supported: intbv objects with a defined bit width, bool  objects,
              signals of the previous objects, and bit strings. All these objects have a defined bit width.

              The first argument base is special as it does not need to have a defined bit width. In addition to
              the  previously  mentioned  objects, unsized intbv, int and long objects are supported, as well as
              signals of such objects.

              Return type
                     intbv

   downrange
       downrange(high[, low=0])
              Generates a downward range list of integers.

              This function is modeled after the standard range function, but works in the  downward  direction.
              The returned interval is half-open, with the high index not included. low is optional and defaults
              to  zero.  This function is especially useful in conjunction with the intbv class, that also works
              with downward indexing.

   instances
       instances()
              Looks up all MyHDL instances in the local name space and returns them in a list.

              Return type
                     list

   Co-simulation
   MyHDL
       class Cosimulation(exe, **kwargs)
              Class to construct a new Cosimulation object.

              The exe argument is the command to execute an HDL simulation, which can be either a string of  the
              entire  command  line  or  a  list  of  strings.   In  the  latter  case, the first element is the
              executable, and subsequent elements are program arguments. Providing a list  of  arguments  allows
              Python to correctly handle spaces or other characters in program arguments.

              The  kwargs keyword arguments provide a named association between signals (regs & nets) in the HDL
              simulator and signals in the MyHDL simulator. Each keyword should be a name listed in a  $to_myhdl
              or $from_myhdl call in the HDL code. Each argument should be a Signal declared in the MyHDL code.

   Verilog
       $to_myhdl(arg, [, arg ...])
              Task  that  defines  which  signals (regs & nets) should be read by the MyHDL simulator. This task
              should be called at the start of the simulation.

       $from_myhdl(arg, [, arg ...])
              Task that defines which signals should be driven by the MyHDL simulator. In Verilog, only regs can
              be specified. This task should be called at the start of the simulation.

   Conversion to Verilog and VHDL
   Conversion
       toVerilog(func [, *args] [, **kwargs])
                 Converts a MyHDL design instance to equivalent Verilog code, and also generates a test bench to
                 verify it. func is a function that returns an instance.  toVerilog calls func under its control
                 and passes *args and **kwargs to the call.

                 The return value is the same as would be returned by the call func(*args, **kwargs). It  should
                 be assigned to an instance name.

                 The  top-level  instance name and the basename of the Verilog output filename is func.func_name
                 by default.

                 For more information about the restrictions on convertible MyHDL code, see section  conv-subset
                 in Chapter conv.

              toVerilog has the following attribute:

              name   This attribute is used to overwrite the default top-level instance name and the basename of
                     the Verilog output filename.

              directory
                     This  attribute  is used to set the directory to which converted verilog files are written.
                     By default, the current working directory is used.

              timescale
                     This attribute is used to set the timescale in Verilog format. The assigned value should be
                     a string. The default timescale is "1ns/10ps".

       toVHDL(func[, *args][, **kwargs])
              Converts a MyHDL design instance to equivalent VHDL code. func  is  a  function  that  returns  an
              instance. toVHDL calls func under its control and passes *args and **kwargs to the call.

              The  return  value  is  the same as would be returned by the call func(*args, **kwargs). It can be
              assigned to an instance name.  The top-level instance name and the basename of the Verilog  output
              filename is func.func_name by default.

              toVHDL has the following attributes:

              name   This attribute is used to overwrite the default top-level instance name and the basename of
                     the VHDL output.

              directory
                     This  attribute  is used to set the directory to which converted VHDL files are written. By
                     default, the current working directory is used.

              component_declarations
                     This attribute can be used to add component declarations to the VHDL output. When a  string
                     is assigned to it, it will be copied to the appropriate place in the output file.

              library
                     This  attribute  can be used to set the library in the VHDL output file. The assigned value
                     should be a string. The default library is work.

              std_logic_ports
                     This boolean attribute can be used to have only  std_logic  type  ports  on  the  top-level
                     interface  (when  True)  instead  of  the  default  signed/unsigned  types (when False, the
                     default).

   User-defined Verilog and VHDL code
       User-defined code can be inserted in the Verilog or VHDL output through the use of  function  attributes.
       Suppose  a function <func> defines a hardware module. User-defined code can be specified for the function
       with the following function attributes:

       <func>.vhdl_code
              A template string for user-defined code in the VHDL output.

       <func>.verilog_code
              A template string for user-defined code in the Verilog output.

       When such a function attribute is defined, the normal conversion process is bypassed and the user-defined
       code is inserted instead.  The template strings should  be  suitable  for  the  standard  string.Template
       constructor.  They  can  contain interpolation variables (indicated by a $ prefix) for all signals in the
       context. Note that the function attribute can be defined anywhere where <func> is visible, either outside
       or inside the function itself.

       These function attributes cannot be used with generator functions or decorated local functions, as  these
       are not elaborated before simulation or conversion.  In other words, they can only be used with functions
       that define structure.

   Conversion output verification
       MyHDL  provides an interface to verify converted designs.  This is used extensively in the package itself
       to verify the conversion functionality. This capability is exported by the package so that users can  use
       it also.

   Verification interface
       All functions related to conversion verification are implemented in the myhdl.conversion package.

       verify(func[, *args][, **kwargs])
              Used like toVHDL and  toVerilog. It converts MyHDL code, simulates both the MyHDL code and the HDL
              code and reports any differences. The default HDL simulator is GHDL.

              This function has the following attribute:

              simulator
                     Used to set the name of the HDL simulator. "GHDL" is the default.

       analyze(func[, *args][, **kwargs])
              Used  like  toVHDL and toVerilog. It converts MyHDL code, and analyzes the resulting HDL.  Used to
              verify whether the HDL output is syntactically correct.

              This function has the following attribute:

              simulator
                     Used to set the name of the HDL simulator used to analyze the code. "GHDL" is the default.

   HDL simulator registration
       To use a HDL simulator to verify conversions, it needs to be registered first. This is  needed  once  per
       simulator.

       A number of HDL simulators are preregistered in the MyHDL distribution, as follows:
                                    ┌────────────┬──────────────────────────────┐
                                    │ Identifier │ Simulator                    │
                                    ├────────────┼──────────────────────────────┤
                                    │ "GHDL"     │ The GHDL VHDL simulator      │
                                    ├────────────┼──────────────────────────────┤
                                    │ "vsim"     │ The ModelSim VHDL simulator  │
                                    ├────────────┼──────────────────────────────┤
                                    │ "icarus"   │ The Icarus Verilog simulator │
                                    ├────────────┼──────────────────────────────┤
                                    │ "cver"     │ The cver Verilog simulator   │
                                    ├────────────┼──────────────────────────────┤
                                    │ "vlog"     │ The Modelsim VHDL simulator  │
                                    └────────────┴──────────────────────────────┘

       Of course, a simulator has to be installed before it can be used.

       If  another  simulator  is required, it has to be registered by the user.  This is done with the function
       registerSimulation that lives in the module  myhdl.conversion._verify.  The  same  module  also  has  the
       registrations for the predefined simulators.

       The  verification  functions  work by comparing the HDL simulator output with the MyHDL simulator output.
       Therefore, they have to deal with the specific details  of  each  HDL  simulator  output,  which  may  be
       somewhat  tricky.  This is reflected in the interface of the registerSimulation function. As registration
       is rarely needed, this interface is not further described here.

       Please refer to the source code in myhdl.conversion._verify to learn how registration works. If you  need
       help, please contact the MyHDL community.

WHAT'S NEW IN MYHDL 0.11

   The isasync arguments
       The async argument has been replaced with isasync to avoid the Python 3.7 keyword conflict.

PYTHON 3 SUPPORT

       MyHDL  supports Python 3.4 and above.  At the moment, core functions, cosimulation and Verilog conversion
       work perfectly.  However, there are a few unresolved VHDL conversion bugs.

       All users are encouraged to try out their existing projects and  tests  with  Python  3  and  submit  bug
       reports if anything goes wrong.

WHAT'S NEW IN MYHDL 0.10

   The block decorator
   Rationale
       The  historical approach for hierarchy extraction in MyHDL suffers from significant issues.  This results
       in complex code, a number of non-intuitive API concepts, and difficulties for future development.

       In this release, a new block decorator is introduced to address these issues.

       For an in-depth discussion, see mep-114.

   API
       block() :noindex:
              The  block  decorator  enables  a  method-based  API  which   is   more   consistent,   simplifies
              implementation, and reduces the size of the myhdl namespace.

              The  methods  work  on  block  instances,  created  by calling a function decorated with the block
              decorator:

                 @block
                 def myblock(<ports>):
                 ...
                 return <instances>

                 inst = myblock(<port-associations>)
                 # inst supports the methods of the block instance API

       The API on a block instance looks as follows:

       <block_instance>.run_sim(duration=None)
              Run a simulation "forever" (default) or for a specified duration.

       <block_instance>.config_sim(backend='myhdl', trace=False)
              Optional simulation configuration:

              backend: Defaults to 'myhdl

              trace: Enable waveform tracing, default False.

       <block_instance>.quit_sim()
              Quit an active simulation. This is method is currently required because only a  single  simulation
              can be active.

       <block_instance>.convert(hdl='Verilog', **kwargs)
              Converts MyHDL code to a target HDL.

              hdl: 'VHDL' or 'Verilog'. Defaults to Verilog.

              Supported keyword arguments:

              path: Destination folder. Defaults to current working dir.

              name: Module and output file name. Defaults to self.mod.__name__.

              trace: Whether the testbench should dump all signal waveforms. Defaults to False.

              testbench: Verilog only. Specifies whether a testbench should be created.  Defaults to True.

              timescale: timescale parameter. Defaults to '1ns/10ps'. Verilog only.

       <block_instance>.verify_convert()
              Verify conversion output, by comparing target HDL simulation log with MyHDL simulation log.

       <block_instance>.analyze_convert()
              Analyze conversion output by compilation with target HDL compiler.

   Backwards compatibility issues
       In the 0.10 release, the old API still available next to the new API based on the block decorator.

       It  is  likely  that  the  old deprecated API will be removed in a future release, resulting in backwards
       incompatibility for legacy code. Therefore, users are encouraged to start using  the  new  API  in  their
       development methodology.

WHAT'S NEW IN MYHDL 0.9

   Python 3 support
       Experimental  Python  3  support  has  been added to MyHDL 0.9.  This was a major effort to modernize the
       code. As a result, Python 2 and 3 are supported from a single codebase.

       See /python3 for more info.

   Interfaces (Conversion of attribute accesses)
   Rationale
       Complex designs often have many signals that are passed to different  levels  of  hierarchy.   Typically,
       many signals logically belong together. This can be modelled by an interface: an object that has a number
       of  Signal  objects  as its attributes.  Grouping signals into an interface simplifies the code, improves
       efficiency, and reduces errors.

       The following is an example of an interface definition:

          class Complex:
              def __init__(self, min=-2, max=2):
                  self.real = Signal(intbv(0, min=min, max=max))
                  self.imag = Signal(intbv(0, min=min, max=max))

       Although previous versions supported interfaces for modeling, they were not convertible.  MyHDL  0.9  now
       supports conversion of designs that use interfaces.

       The following is an example using the above Complex interface definition:

          a,b = Complex(-8,8), Complex(-8,8)
          c = Complex(-128,128)

          def complex_multiply(clock, reset, a, b, c):

              @always_seq(clock.posedge, reset=reset)
              def cmult():
                  c.real.next = (a.real*b.real) - (a.imag*b.imag)
                  c.imag.next = (a.real*b.imag) + (a.imag*b.real)

              return cmult

   Solution
       The  proposed  solution is to create unique names for attributes which are used by MyHDL generators.  The
       converter will create a unique name by using the name of the parent and the name of the  attribute  along
       with  the  name  of the MyHDL module instance. The converter will essentially replace the "." with an "_"
       for each interface element. In essence, interfaces are supported using hierarchical  name  expansion  and
       name mangling.

       Note  that  the  MyHDL converter supports interfaces, even though the target HDLs do not. This is another
       great example where the converter supports a high-level feature that is not available in the target HDLs.

   See also
       For additional information see the original proposal mep-107.

   Other noteworthy improvements
   ConcatSignal interface
       The interface of ConcatSignal was enhanced. In addition to signals, you can now also use constant  values
       in the concatenation.

   std_logic type ports
       toVHDL has a new attribute std_logic_ports. When set, only std_logic type ports are used in the interface
       of the top-level VHDL module.

   Development flow
       The  MyHDL  development  flow  has  been  modernized  by moving to git and github for version control. In
       addition, travis has set up so that all pull  requests  are  tested  automatically,  enabling  continuous
       intergration.

   Acknowledgments
       The  Python  3  support  effort  was  coordinated  by  Keerthan  Jaic,  who  also implemented most of if.
       Convertible interfaces were championed by Chris Felton, and implemented by Keerthan Jaic.

       MyHDL development is a collaborative effort, as can be seen on github.  Thanks  to  all  who  contributed
       with suggestions, issues and pull requests.

WHAT'S NEW IN MYHDL 0.8

   Modular bit vector types
   Rationale
       In  hardware  modeling,  there  is  often  a need for the elegant modeling of wrap-around behavior. intbv
       instances don't provide this automatically, because they assert that any assigned  value  is  within  the
       bound  constraints.   Therefore,  one  has  currently  has to use other language features for wrap-around
       modeling.

       Often, this is straightforward. For example, the wrap-around condition for a  counter  is  often  decoded
       explicitly,  as  it is needed for other purposes. Also, the modulo operator provides an elegant one-liner
       in most scenarios.

       However, in some important cases the current solution is not satisfactory. For example, we would like  to
       describe a free running counter using a variable and augmented assignment as follows:

          count += 1

       This  is  not  possible  with the intbv type, as we cannot add the modulo behavior to this description. A
       similar problem exist of for a left shift as follows:

          shifter <<= 4

       These operations can only supported directly with a new type.  For these reasons, it was felt  that  this
       would be a useful addition to MyHDL.

   Solution
       The  proposed  solution  is to borrow the idea behind Ada modular types.  These are natural integer types
       with wrap-around behaviour.

       The wrap-around behavior of  modular  types  is  based  on  the  sound  mathematical  concept  of  modulo
       arithmetic. Therefore, the modulus is not limited to powers of 2.

       Ada's  modular  type  is  called  mod.  In MyHDL, we want also want to give it "bit-vector" support, like
       intbv. Therefore, proposed MyHDL type is called modbv.

   Implementation
       modbv is implemented as a subclass of  intbv.  The two classes  have  an  identical  interface  and  work
       together in a straightforward way for arithmetic operations.

       The only difference is how the bounds are handled: out-of-bound values result in an error with intbv, and
       in  wrap-around  with  modbv. The Wrap-around behavior would be defined as follows, with val denoting the
       current value and min/max the bounds:

          val = (val - min) % (max - min) + min

   Interface
       class modbv([val=0] [, min=None] [, max=None])
              The modbv class implements modular bit vector types.

              It is implemented as a subclass of intbv and supports the  same  parameters  and  operators.   The
              difference  is  in  the  handling of the min and max boundaries.  Instead of throwing an exception
              when those constraints are exceeded, the value of modbv objects  wraps  around  according  to  the
              following formula:

                 val = (val - min) % (max - min) + min

              This  formula  is  a  generalization  of  modulo  wrap-around  behavior  that is often useful when
              describing hardware system behavior.

   Conversion
       Full-range modbv objects are those where the max bound is a power of 2, and the min bound  is  0  or  the
       negative  of the max bound.  For these objects, conversion worked out-of-the-box because this corresponds
       to the target types in Verilog and VHDL.

       Currently, conversion is restricted  to  full-range  modbv  objects.   It  may  be  possible  to  support
       conversion  of  the  modulo  behavior of more general cases, but this requires more sophistication in the
       converter. This may be considered in the future.

   See also
       For a more in-depth discussion, see mep-106.

   always_seq decorator
   Rationale
       In classical synthesizable RTL coding, the reset behavior is described explicitly. A typical template  is
       as follows:

          @always(clock.posedge, reset.negedge)
          def seq():
              if reset == 0:
                  <reset code>
              else:
                  <functional code>

       The  reset  behavior  is  described  using a the top-level if-else structure with a number of assignments
       under the  if.  A  significant  piece  of  code  at  a  prominent  location  is  therefore  dedicated  to
       non-functional behavior.

       Reset  behavior  coding is error-prone. For a proper gate-level implementation, most if not all registers
       should typically be reset. However, it is easy to forget  some  reset  assignments.  Such  bugs  are  not
       necessarily easily detected during RTL or gate-level simulations.

       In  the  template, the edge that asserts reset is in the sensitivity list. It is easy to forget this, and
       in that case the reset will not behave asynchronously as intended but synchronously. Note also that it is
       somewhat strange to specify an edge sensitivity when describing asynchronous behavior.

   Solution
       The proposed solution is to infer the reset structure automatically.  The main idea is to use the initial
       values of signals as the specification of reset values. This is possible in MyHDL,  because  all  objects
       are  constructed  with  an  initial  value.  The  assumption is that the initial value also specifies the
       desired reset value.

       The solution is implemented with two new MyHDL constructs. The  first  one  is  a  new  decorator  called
       always_seq.  Using  this  decorator,  code  with  identical  behavior  as  in the previous section can be
       described as follows:

          @always_seq(clock.posedge, reset=reset)
              <functional code>

       The always_seq decorator takes two arguments: a clock edge and a reset signal. It inspects  the  code  to
       find the registers, and uses the initial values to construct the reset behavior.

       The second construct is a specialized signal subclass called ResetSignal. It is used as follows:

          reset = ResetSignal(1, active=0, async=True)

       The  ResetSignal constructor has three arguments: the initial value as usual, an active argument with the
       active level, and  an  async  argument  that  specifies  whether  the  reset  style  is  asynchronous  or
       synchronous.

       The proposed solution has some very desirable features.

       Explicit  reset  behavior  coding is no longer necessary. Code reviewers are thus no longer distracted by
       non-functional code. It is sufficient to check the initial values to verify whether the  reset  value  is
       correctly specified. Moreover, one indentation level is saved for functional coding.

       Even  more  importantly,  the reset structure is correct by construction. All registers are automatically
       included in the reset behavior, and the sensitivity list is automatically correct according to the  reset
       style.

       Traditionally,  the  reset  behavior is spread out over all sequential processes. Therefore, it has to be
       debugged by investigating all those processes. Even worse, if a  change  in  style  or  active  level  is
       required,  all  processes  are  affected. In contrast, with the proposed technique all reset features are
       specified at single location in the ResetSignal constructor. Changes are trivial. For example, to  change
       to an active high synchronous reset one merely has to change the constructor as follows:

          reset = ResetSignal(1, active=1, async=False)

       Occasionally,  it is useful to have registers without reset at all. The proposed technique is also useful
       in that case. In particular, the always_seq decorator accepts None as the reset argument:

          @always_seq(clock.posedge, reset=None)

       A reviewer will have no doubt what the intention is. In contrast, in the case  of  a  traditional  always
       block,  the reviewer may think that the designer has delayed the detailed reset coding for later and then
       forgotten about it.

   Interface
       always_seq(edge, reset)
              The always_seq decorator is used to describe sequential (clocked) logic.

              The edge parameter should be a clock edge (clock.posedge or clock.negedge).  The  reset  parameter
              should a ResetSignal object.

       class ResetSignal(val, active, async)
                 This  Signal  subclass  defines  reset signals. val, active, and async are mandatory arguments.
                 val is a boolean value that specifies the  initial  value,  active  is  a  boolean  value  that
                 specifies  the  active  level.   async  is  a  boolean  value  that  specifies the reset style:
                 asynchronous (True) or asynchronous (False).

   Conversion
       As modeling the reset behavior is a typical task in synthesizable RTL coding, the proposed  technique  is
       fully convertible to Verilog and VHDL.

   Limitations
   All registers in a process are reset
       All  registers in a process are automatically included in the reset behavior. If it is the intention that
       some registers should not be reset, those registers and the corresponding code should be factored out  in
       a separate process.

       Actually,  this  is  not  really a limitation but a feature. If some registers in a process are reset and
       others not, a synthesis tool may generate undesirable feedback loops that are  active  during  the  reset
       condition. This is not good practice and probably not the intention.

   Register inferencing from variables is not supported
       An  important  limitation  is  that the proposed technique is limited to registers inferred from signals.
       Registers inferred from variables are not supported, because such state variables cannot be described  in
       classic  functions  (in  particular  the  functions  required  by MyHDL decorators such as always_seq and
       always).

       In fact, the reason is a Python2 limitation. Currently, to infer registers from variables, one has to use
       the instance decorator and declare the state variables outside an infinite while True loop.

       In Python3, this limitation can be lifted with the introduction of the nonlocal  declaration.  This  will
       make it possible for functions to modify variables in the enclosing scope. It should be possible to adapt
       the always_seq and always decorators to support such variables.

   See also
       For a more in-depth discussion, see mep-109.

   Other improvements
   Conversion of top-level class methods
       Often  it  is  desirable  to  embed  an  HDL module description in a class.  Previous versions would only
       convert a class method if it was not the top-level.  This release adds the conversion of top-level  class
       methods.

   Example
          class DFilter(object):
              def __init__(self,delay_length=3,fs=1):
                  <init code>
              def nulls(self):
                  <support method code>
              def m_top(self,clock,reset,x,y):
                  <myhdl module code>

          clock = Signal(bool(0))
          reset = ResetSignal(0,active=0,async=True)
          x = Signal(intbv(0, min=-8, max=8))
          y = Signal(intbv(0, min=-64, max=64))

          filt = DFilter()
          toVerilog(filt.m_top,clock,reset,x,y)
          toVHDL(filt.m_top,clock,reset,x,y)

   See also
       For a more in-depth discussion, see mep-108.

   Tracing lists of signals
       Tracing  lists  of signals is now supported.  Contributed by Frederik Teichtert, http://teichert-ing.de .
       The following shows how the list of signals are displayed in a waveform viewer

          delay_taps = [Signal(intbv(0,min=-8,max=8)) for ii in range(3)]
       [image]

   library attribute for toVHDL
       toVHDL now has a library function that can be used to set the  library  name  in  the  VHDL  output.  The
       assigned value should be a string.  The default library is "work".

   timescale attribute for traceSignals
       traceSignals  now  has a timescale attribute that can be used to set the timescale in the VCD output. The
       assigned value should be a string.  The default timescale is "1ns".

   Acknowledgments
       Several people have contributed to MyHDL 0.8 by giving feedback,  making  suggestions,  fixing  bugs  and
       implementing features.  In particular, I would like to thank Christopher Felton and Frederik Teichert.

       I would also like to thank Easics for the opportunity to use MyHDL in industrial projects.

WHAT'S NEW IN MYHDL 0.7

   Conversion to VHDL/Verilog rewritten with the ast module
       The most important code change is a change that hopefully no-one will notice :-).  The conversion code is
       now  based on the ast package instead of the compiler package.  Since Python 2.6, the compiler package is
       deprecated and replaced by the new ast package in the standard library. In Python 3, the compiler package
       is no longer available.

       This was a considerable effort, spent on re-implementing existing behavior instead of on new  interesting
       features.   This  was unfortunate, but it had to be done with priority.  Now the conversion code is ready
       for the future.

   Shadow signals
   Background
       Compared to HDLs such as VHDL and Verilog, MyHDL signals are less flexible for structural  modeling.  For
       example,  slicing  a signal returns a slice of the current value. For behavioral code, this is just fine.
       However, it implies that you cannot use such as slice in  structural  descriptions.  In  other  words,  a
       signal  slice  cannot  be  used as a signal.  To solve these issues, a new concept was introduced: shadow
       signals.

       The whole reasoning behind shadow signals is explained in more detail in mep-105.

   Introducing shadow signals
       A shadow signal is related to another signal or signals as a shadow to its parent object. It follows  any
       change  to  its  parent  signal  or  signals  directly.  However,  it is not the same as the original: in
       particular, the user cannot assign to a shadow signal. Also, there may be a delta cycle delay  between  a
       change  in  the  original  and  the corresponding change in the shadow signal. Finally, to be useful, the
       shadow signal performs some kind of transformation of the values of its parent signal or signals.

       A shadow signal is convenient because it is directly constructed from its parent signals. The constructor
       infers everything that's needed: the type info, the initial value, and the transformation of  the  parent
       signal  values.  For  simulation,  the  transformation  is  defined by a generator which is automatically
       created and added to the list of generators to be simulated. For conversion, the  constructor  defines  a
       piece of dedicated Verilog and VHDL code which is automatically added to the converter output.

       Currently,  three  kinds  of  shadow  signals have been implemented.  The original inspiration for shadow
       signals was to have solution for structural slicing. This is the purpose of  the  _SliceSignal  subclass.
       The opposite is also useful: a signal that shadows a composition of other signals. This is the purpose of
       the ConcatSignal subclass.

       As often is the case, the idea of shadow signals had some useful side effects.  In particular, I realized
       that the TristateSignal proposed in mep-103  could be interpreted as a shadow signal of its drivers. With
       the  machinery  of  the  shadow  signal  in  place,  it  became easier to support this for simulation and
       conversion.

   Concrete shadow signal subclasses
       class _SliceSignal(sig, left[, right=None])

       This class implements read-only structural slicing and indexing. It creates a new signal that shadows the
       slice or index of the parent signal sig. If the right parameter is omitted, you get indexing  instead  of
       slicing.   Parameters  left   and  right have the usual meaning for slice indices: in particular, left is
       non-inclusive but right is inclusive. sig should be appropriate for slicing and indexing, which means  it
       should be based on intbv in practice.

       The  class  constructors  is not intended to be used explicitly. Instead, regular signals now have a call
       interface that returns a _SliceSignal:

       Signal.__call__(left[, right=None])

       Therefore, instead of:

          sl = _SliceSignal(sig, left, right)

       you can do:

          sl = sig(left, right)

       Obviously, the call interface was intended to be similar to a slicing interface. Of  course,  it  is  not
       exactly  the  same  which  may  seem  inconvenient.  On the other hand, there are Python functions with a
       similar slicing functionality and a similar interface, such as the range function.   Moreover,  the  call
       interface conveys the notion that something is being constructed, which is what really happens.

       class ConcatSignal(*args)

       This  class creates a new signal that shadows the concatenation of its parent signal values. You can pass
       an arbitrary number of signals to the constructor. The signal arguments should  be  bit-oriented  with  a
       defined number of bits.

       class TristateSignal(val)
                 This  class is used to construct a new tristate signal. The underlying type is specified by the
                 val parameter.  It is a Signal subclass and has the usual attributes, with  one  exception:  it
                 doesn't support the next attribute. Consequently, direct signal assignment to a tristate signal
                 is  not  supported.   The  initial  value  is  the tristate value None.  The current value of a
                 tristate is determined by resolving the values from its drivers. When exactly one driver  value
                 is  different  from  None, that is the resolved value; otherwise it is None. When more than one
                 driver value is different from None, a contention warning is issued.

       This class has the following method:

       driver()
                 Returns a new driver to the tristate signal. It is initialized to None.  A driver object is  an
                 instance  of  a  special  SignalType subclass. In particular, its next attribute can be used to
                 assign a new value to it.

   Example
       A typical application of shadow signals is conversion of list of signals to bit vectors and vice versa.

       For example, suppose we have a system with N requesters that  need  arbitration.  Each  requester  has  a
       request output and a grant input. To connect them in the system, we can use list of signals. For example,
       a list of request signals can be constructed as follows:

          request_list = [Signal(bool()) for i in range(M)]

       Suppose that an arbiter module is available that is instantiated as follows:

          arb = arbiter(grant_vector, request_vector, clock, reset)

       The  request_vector  input is a bit vector that can have any of its bits asserted. The grant_vector is an
       output bit vector with just a single bit asserted, or none.  Such a module  is  typically  based  on  bit
       vectors  because  they are easy to process in RTL code. In MyHDL, a bit vector is modeled using the intbv
       type.

       We need a way to "connect" the list of signals to the bit vector and vice versa. Of  course,  we  can  do
       this  with  explicit  code, but shadow signals can do this automatically. For example, we can construct a
       request_vector as a ConcatSignal object:

          request_vector = ConcatSignal(*reversed(request_list)

       Note that we reverse the list first. This is done because the index range of lists is the inverse of  the
       range of intbv bit vectors.  By reversing, the indices correspond to the same bit.

       The inverse problem exist for the grant_vector. It would be defined as follows:

          grant_vector = Signal(intbv(0)[M:])

       To  construct a list of signals that are connected automatically to the bit vector, we can use the Signal
       call interface to construct _SliceSignal objects:

          grant_list = [grant_vector(i) for i in range(M)]

       Note the round brackets used for this type of slicing. Also, it may not be necessary  to  construct  this
       list explicitly. You can simply use grant_vector(i) in an instantiation.

       To  decide when to use normal or shadow signals, consider the data flow. Use normal signals to connect to
       outputs. Use shadow signals to transform these signals so that they can be used as inputs.

   Using Signal and intbv objects as indices
       Previously, it was necessary convert Signal and intbv objects  explicitly  to  int  when  using  them  as
       indices  for  indexing  and  slicing.  This  conversion  is  no  longer required; the objects can be used
       directly.  The corresponding classes now have an __index__ method that takes care of the type  conversion
       automatically.  This feature is fully supported by the VHDL/Verilog converter.

   New configuration attributes for conversion file headers
       New configuration attributes are available to control the file headers of converted output files.

       toVerilog.no_myhdl_header
              Specifies  that MyHDL conversion to Verilog should not generate a default header. Default value is
              False.

       toVHDL.no_myhdl_header
              Specifies that MyHDL conversion to VHDL should not generate a default  header.  Default  value  is
              False.

       toVerilog.header
              Specifies an additional custom header for Verilog output.

       toVHDL.header
              Specifies an additional custom header for VHDL output.

       The  value  for  the  custom headers should be a string that is suitable for the standard string.Template
       constructor.  A number of variables (indicated by a $ prefix) are  available  for  string  interpolation.
       For example, the standard header is defined as follows:

          myhdl_header = """\
          -- File: $filename
          -- Generated by MyHDL $version
          -- Date: $date
          """

       The same interpolation variables are available in custom headers.

   Conversion propagates docstrings
       The converter now propagates comments under the form of Python docstrings.

       Docstrings  are  typically  used in Python to document certain objects in a standard way. Such "official"
       docstrings are put into the converted output at appropriate locations.  The converter  supports  official
       docstrings for the top level module and for generators.

       Within  generators,  "nonofficial"  docstrings  are  propagated also. These are strings (triple quoted by
       convention) that can occur anywhere between statements.

       Regular Python comments are ignored by the Python parser, and they are not present  in  the  parse  tree.
       Therefore,  these  are not propagated. With docstrings, you have an elegant way to specify which comments
       should be propagated and which not.

   New method to specify user-defined code
       The current way to specify user-defined code for conversion  is  through  the  __vhdl__  and  __verilog__
       hooks.  This method has a number of disadvantages.

       First, the use of "magic" variables (whose names start and end with double underscores) was a bad choice.
       According  to  Python  conventions,  such  variables  should  be reserved for the Python language itself.
       Moreover, when new hooks would become desirable, we would have to specify additional magic variables.

       A second problem that standard Python strings were used to define the user-defined output. These  strings
       can  contain  the  signal  names  from  the context for interpolation. Typically, these are multiple-line
       strings that may be quite lengthy. When something goes wrong with the  string  interpolation,  the  error
       messages may be quite cryptic as the line and column information is not present.

       For  these  reasons,  a  new  way  to  specify  user-defined  code has been implemented that avoids these
       problems.

       The proper way to specify meta-information of a function is  by  using  function  attributes.  Suppose  a
       function <func> defines a hardware module. We can now specify user-defined code for it with the following
       function attributes:

       <func>.vhdl_code
              A template string for user-defined code in the VHDL output.

       <func>.verilog_code
              A template string for user-defined code in the Verilog output.

       When such a function attribute is defined, the normal conversion process is bypassed and the user-defined
       code  is  inserted  instead.   The  template  strings should be suitable for the standard string.Template
       constructor. They can contain interpolation variables (indicated by a $ prefix) for all  signals  in  the
       context. Note that the function attribute can be defined anywhere where <func> is visible, either outside
       or inside the function itself.

       The  old method for user-defined code is still available but is deprecated and will be unsupported in the
       future.

   More powerful mapping to case statements
       The converter has become more powerful to map if-then-else structures to  case  statements  in  VHDL  and
       Verilog. Previously, only if-then-else structures testing enumerated types were considered.  Now, integer
       tests are considered also.

   Small changes
   SignalType as the base class of Signals
       Signal  has  become  a  function  instead  of  a class. It returns different Signal subtypes depending on
       parameters. This implies that you cannot use Signal for type checking.

       The base type of all Signals is now SignalType.  This type can be used to check whether an  object  is  a
       Signal instance.

   Default value of intbv objects
       The  default  initial  value  of  an  intbv  object  has  been  changed  from  None  to 0. Though this is
       backward-incompatible, the None value never has been put to good use, so  this  is  most  likely  not  an
       issue.

   Combinatorial always blocks use blocking assignments
       The  converter  now uses blocking assignments for combinatorial always blocks in Verilog. This is in line
       with generally accepted Verilog coding conventions.

   No synthesis pragmas in Verilog output
       The converter no longer outputs the synthesis pragmas full_case and parallel_case. These pragmas do  more
       harm than good as they can cause simulation-synthesis mismatches. Synthesis tools should be able to infer
       the appropriate optimizations from the source code directly.

   Python version
       MyHDL 0.7 requires Python 2.6, mainly because of its dependency on the new ast package.

   Acknowledgments
       Several  people  have  contributed  to  MyHDL 0.7 by giving feedback, making suggestions, fixing bugs and
       implementing features.  In particular, I would like to  thank  Benoit  Allard,  Günter  Dannoritzer,  Tom
       Dillon, Knut Eldhuset, Angel Ezquerra, Christopher Felton, and Jian LUO.

       Thanks to Francesco Balau for packaging MyHDL for Ubuntu.

       I would also like to thank Easics for the opportunity to use MyHDL in industrial projects.

WHAT'S NEW IN MYHDL 0.6

   Conversion to VHDL
   Rationale
       Since  the  MyHDL  to  Verilog  conversion  has  been  developed,  a path to implementation from MyHDL is
       available. Given the widespread support for Verilog, it could thus be argued that there was no real  need
       for a converter to VHDL.

       However,  it  turns out that VHDL is still very much alive and will remain so for the foreseeable future.
       This is especially true for the FPGA market, which is especially interesting for  MyHDL.  It  seems  much
       more  dynamic than the ASIC market. Moreover, because of the nature of FPGA's, FPGA designers may be more
       willing to try out new ideas.

       To convince designers to use a new tool, it should integrate with their current design flow. That is  why
       the  MyHDL  to  VHDL converter is needed. It should lower the threshold for VHDL designers to start using
       MyHDL.

   Advantages
       MyHDL to VHDL conversion offers the following advantages:

       MyHDL integration in a VHDL-based design flow
              Designers can start using MyHDL and benefit from its power and flexibility, within the context  of
              their proven design flow.

       The converter automates a number of hard tasks
              The  converter automates a number of tasks that are hard to do in VHDL directly. For example, when
              mixing unsigned and signed types it can be difficult to describe the desired  behavior  correctly.
              In  contrast,  a MyHDL designer can use the high-level intbv type, and let the converter deal with
              type conversions and resizings.

       MyHDL as an IP development platform
              The possibility to convert the same MyHDL source to equivalent Verilog and VHDL  creates  a  novel
              application: using MyHDL as an IP development platform. IP developers can serve customers for both
              target   languages   from   a   single   MyHDL   code  base.  Moreover,  MyHDL's  flexibility  and
              parametrizability make it ideally suited to this application.

   Solution description
   Approach
       The approach followed to convert MyHDL code to VHDL is identical to the one followed  for  conversion  to
       Verilog in previous MyHDL releases.

       In  particular, the MyHDL code analyzer in the converter is identical for both target languages. The goal
       is that all MyHDL code that can be converted to Verilog can be converted to VHDL also,  and  vice  versa.
       This has been achieved except for a few minor issues due to limitations of the target languages.

   User interface
       Conversion to VHDL is implemented by the following function in the myhdl package:

       toVHDL(func[, *args][, **kwargs])
              Converts  a  MyHDL  design  instance  to  equivalent VHDL code. func is a function that returns an
              instance. toVHDL calls func under its control and passes *args and **kwargs to the call.

              The return value is the same as the one returned by the call  func(*args,  **kwargs).  It  can  be
              assigned  to an instance name.  The top-level instance name and the basename of the Verilog output
              filename is func.func_name by default.

       toVHDL has the following attributes:

       toVHDL.name
              This attribute is used to overwrite the default top-level instance name and the  basename  of  the
              VHDL output.

       toVHDL.component_declarations
              This  attribute  can  be  used  to add component declarations to the VHDL output. When a string is
              assigned to it, it will be copied to the appropriate place in the output file.

   Type mapping
       In contrast to Verilog, VHDL is a strongly typed language. The converter has to  carefully  perform  type
       inferencing,  and  handle  type  conversions and resizings appropriately. To do this right, a well-chosen
       mapping from MyHDL types to VHDL types is crucial.

       MyHDL types are mapped to VHDL types according to the following table:
                         ┌─────────────────────────────┬────────────────────────────┬───────┐
                         │ MyHDL type                  │ VHDL type                  │ Notes │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ intinteger                    │       │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ boolstd_logic                  │ (1)   │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ intbv with min >= 0unsigned                   │ (2)   │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ intbv with  min < 0signed                     │ (2)   │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ enum                        │ dedicated enumeration type │       │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ tuple of int                │ mapped to case statement   │ (3)   │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ list of boolarray of std_logic         │       │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ list of intbv with min >= 0array of unsigned          │ (4)   │
                         ├─────────────────────────────┼────────────────────────────┼───────┤
                         │ list of intbv with min < 0array of signed            │ (4)   │
                         └─────────────────────────────┴────────────────────────────┴───────┘

       Notes:

       1. The VHDL std_logic type is defined in the standard VHDL package IEEE.std_logic_1164.

       2. The VHDL unsigned and signed types used are those from the standard VHDL packages IEEE.numeric_std.

       3. A MyHDL tuple of int is used for ROM inference, and can only be  used  in  a  very  specific  way:  an
          indexing operation into the tuple should be the rhs of an assignment.

       4. All list members should have identical value constraints.

       The table as presented applies to MyHDL variables. They are mapped to VHDL variables (except for the case
       of a tuple of int).

       The  converter also supports MyHDL signals that use bool, intbv or enum objects as their underlying type.
       These are mapped to VHDL signals with a type as specified in the table above.

       The converter supports MyHDL list of signals provided the underlying signal type is either bool or intbv.
       They may be mapped to a VHDL signal with a VHDL type as specified in the table.  However, list of signals
       are not always mapped to a corresponding VHDL signal. See Conversion of lists of signals for more info.

   Template transformation
       There is a difference between VHDL and Verilog in the  way  in  which  sensitivity  to  signal  edges  is
       specified. In Verilog, edge specifiers can be used directly in the sensitivity list. In VHDL, this is not
       possible:  only  signals  can  be  used  in  the  sensitivity  list.  To  check for an edge, one uses the
       rising_edge() or falling_edge() functions in the code.

       MyHDL follows the Verilog scheme to specify edges in the sensitivity  list.  Consequently,  when  mapping
       such  code  to VHDL, it needs to be transformed to equivalent VHDL. This is an important issue because it
       affects all synthesizable templates that infer sequential logic.

       We will illustrate this feature with some examples. This is the MyHDL code for a D flip-flop:

          @always(clk.posedge)
          def logic():
              q.next = d

       It is converted to VHDL as follows:

          DFF_LOGIC: process (clk) is
          begin
              if rising_edge(clk) then
                  q <= d;
              end if;
          end process DFF_LOGIC;

       The converter can handle the more general case. For example, this is MyHDL code for a  D  flip-flop  with
       asynchronous set, asynchronous reset, and preference of set over reset:

          @always(clk.posedge, set.negedge, rst.negedge)
          def logic():
              if set == 0:
                  q.next = 1
              elif rst == 0:
                  q.next = 0
              else:
                  q.next = d

       This is converted to VHDL as follows:

          DFFSR_LOGIC: process (clk, set, rst) is
          begin
              if (set = '0') then
                  q <= '1';
              elsif (rst = '0') then
                  q <= '0';
              elsif rising_edge(clk) then
                  q <= d;
              end if;
          end process DFFSR_LOGIC;

       All  cases  with practical utility can be handled in this way. However, there are other cases that cannot
       be transformed to equivalent VHDL. The converter will detect those cases and give an error.

   Conversion of lists of signals
       Lists of signals are useful for many purposes. For example, they make it  easy  to  create  a  repetitive
       structure. Another application is the description of memory behavior.

       The  converter output is non-hierarchical. That implies that all signals are declared at the top-level in
       VHDL or Verilog (as VHDL signals, or Verilog regs and wires.)  However, some  signals  that  are  a  list
       member  at  some  level  in the design hierarchy may be used as a plain signal at a lower level. For such
       signals, a choice has to be made whether to declare a Verilog memory or VHDL array, or a number of  plain
       signal names.

       If  possible,  plain  signal  declarations  are  preferred, because Verilog memories and arrays have some
       restrictions in usage and tool support.  This is possible if the list syntax  is  strictly  used  outside
       generator code, for example when lists of signals are used to describe structure.

       Conversely,  when  list  syntax  is  used  in some generator, then a Verilog memory or VHDL array will be
       declared. The typical example is the description of RAM memories.

       The converter in the previous MyHDL release had a severe restriction on the latter case: it didn't  allow
       that,  for  a certain signal, list syntax was used in some generator, and plain signal syntax in another.
       This restriction, together with its rather obscure error message, has caused regular user complaints.  In
       this release, this restriction has been lifted.

   Conversion of test benches
   Background
       After  conversion, we obviously want to verify that the VHDL or Verilog code works correctly. In previous
       MyHDL versions, the proposed verification technique was co-simulation: use the same MyHDL test  bench  to
       simulate  the  converted  Verilog code and the original MyHDL code. While co-simulation works well, there
       are a number of issues with it:

       • Co-simulation requires that the HDL simulator has an interface to its internal workings,  such  as  vpi
         for Verilog and vhpi for VHDL.

       • vpi  for  Verilog is well-established and available for open-source simulators such as Icarus and cver.
         However, vhpi for VHDL is much less established; it is unclear whether there is an open source solution
         that is powerful enough for MyHDL's purposes.

       • Even though vpi is a "standard", there are differences  between  various  simulators.  Therefore,  some
         customization is typically required per Verilog simulator.

       • MyHDL  co-simulation  uses unix-style interprocess communication that doesn't work on Windows natively.
         This is an exception to the rest of MyHDL that should run on any Python platform.

       The conclusion is that co-simulation is probably not a viable solution for the VHDL case, and it has some
       disadvantages for Verilog as well.

       The proposed alternative is to convert the test bench itself, so that both test bench and design  can  be
       run  in the HDL simulator. Of course, this is not a fully general solution either, as there are important
       restrictions on the kind of code that can be converted. However, with the additional features  that  have
       been developed, it should be a useful solution for verifying converted code.

   Print statement
       In previous MyHDL versions, print statement conversion to Verilog was supported in a quick and dirty way,
       by merely copying the format string without checks. With the advent of VHDL conversion, this has now been
       implemented  more  rigorously.  This was necessary because VHDL doesn't work with format strings. Rather,
       the format string specification has to be converted to a sequence of VHDL write and writeline calls.

       A print statement with multiple arguments:

          print arg1, arg2, ...

       is supported. However, there are restrictions on the arguments.  First, they should  be  of  one  of  the
       following forms:

          arg
          formatstring % arg
          formatstring % (arg1, arg2, ...)

       where arg is a bool, int, intbv, enum, or a Signal of these types.

       The  formatstring  contains ordinary characters and conversion specifiers as in Python. However, the only
       supported conversion specifiers are %s and %d.   Justification  and  width  specification  are  thus  not
       supported.

       Printing without a newline:

          print arg1 ,

       is  not  supported.  This  is because the solution is based on std.textio. In VHDL std.textio, subsequent
       write() calls to a line are only printed upon a writeline() call. As a normal print  implies  a  newline,
       the  correct  behavior  can  be  guaranteed, but for a print without newline this is not possible. In the
       future, other techniques may be used and this restriction may be lifted.

   Assert statement
       An assert statement in Python looks as follow:

          assert test_expression

       It can be converted provided test_expression is convertible.

   Delay objects
       Delay objects are constructed as follows:

          delay(t)

       with t an integer. They are used in yield statements and as the argument of always decorators, to specify
       delays.  They can now be converted.

   Methodology notes
       The question is whether the conversion restrictions permit  one  to  develop  sufficiently  complex  test
       benches. In this section, we present some insights about this.

       The  most  important  restrictions  are  the  types that can be used. These remain "hardware-oriented" as
       before.

       Even in the previous MyHDL release, the "convertible subset" was much wider than the "synthesis  subset".
       For example, while and raise statement were already convertible.

       The  support  for  delay  objects  is  the most important new feature to write high-level models and test
       benches.

       With the print statement, simple debugging can be done.

       Of particular interest is the assert statement. Originally,  assert  statements  were  only  intended  to
       insert  debugging  assertions  in  code. Recently, there is a tendency to use them to write self-checking
       unit tests, controlled by unit test frameworks such as py.test. In particular, they are a powerful way to
       write self-checking test benches for MyHDL designs. As assert statements are  now  convertible,  a  whole
       test suite in MyHDL can be converted to an equivalent test suite in Verilog and VHDL.

       Finally,  the  same techniques as for synthesizable code can be used to master complexity. In particular,
       any code outside generators  is  executed  during  elaboration,  and  therefore  not  considered  in  the
       conversion  process.  This feature can for example be used for complex calculations that set up constants
       or expected results.  Furthermore, a tuple of ints can be used to hold a table of  values  that  will  be
       mapped to a case statement in Verilog and VHDL.

   Conversion output verification
       NOTE:
          This  functionality  is  not  needed  in a typical design flow. It is only relevant to debug the MyHDL
          converter itself.

   Approach
       To verify the converter output, a methodology has been developed and implemented  that  doesn't  rely  on
       co-simulation and works for both Verilog and VHDL.

       The  solution  builds  on  the  features  explained  in  section Conversion of test benches.  The idea is
       basically to convert the test bench as well as the functional code. In particular,  print  statements  in
       MyHDL  are  converted  to  equivalent statements in the HDL. The verification process consists of running
       both the MyHDL and the HDL simulation, comparing the simulation output, and reporting any differences.

       The goal is to make the verification process as easy as possible. The use of print statements to debug  a
       design  is a very common and simple technique. The verification process itself is implemented in a single
       function with an interface that is identical to toVHDL and toVerilog.

       As this is a native Python solution, it runs on any platform on which the HDL simulator  runs.  Moreover,
       any  HDL  simulator  can  be used as no vpi or vhpi capabilities are needed. Of course, per HDL simulator
       some customization is required to define the details on how it is used. This needs to be  done  once  per
       HDL simulator and is fully under user control.

   Verification interface
       All  functions  related  to  conversion verification are implemented in the myhdl.conversion package. (To
       keep the myhdl namespace clean, they are not available from the myhdl namespace directly.)

       verify(func[, *args][, **kwargs])
              Used like toVHDL. It converts MyHDL code, simulates both the MyHDL  code  and  the  HDL  code  and
              reports any differences. The default HDL simulator is GHDL.

       analyze(func[, *args][, **kwargs])
              Used  like toVHDL. It converts MyHDL code, and analyzes the resulting HDL.  Used to verify whether
              the HDL output is syntactically correct.

       The two previous functions have the following attribute:

       analyze.simulator
              Used to set the name of the HDL analyzer. GHDL is the default.

       verify.simulator
              Used to set the name of the HDL simulator. GHDL is the default.

   HDL simulator registration
       To be able to use a HDL simulator to verify conversions, it needs to be registered first. This is  needed
       once per simulator (or rather, per set of analysis and simulation commands). Registering is done with the
       following function:

       registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulate=None, offset=0)
              Registers  a  particular  HDL simulator to be used by  verify and analyze. name is the name of the
              simulator.  hdl specifies the HDL: "VHDL" or "Verilog".  analyze is a command  string  to  analyze
              the  HDL  source  code.   elaborate is a command string to elaborate the HDL code. This command is
              optional.  simulate is a command string to simulate the HDL code.  offset is an integer specifying
              the number of initial lines to be ignored from the HDL simulator output.

              The command strings should be string templates that refer to the topname variable  that  specifies
              the  design name. The templates can also use the unitname variable which is the lower case version
              of topname.  The command strings can assume that a subdirectory called work is  available  in  the
              current working directory. Analysis and elaboration results can be put there if desired.

              The analyze function runs the analyze command.  The verify function runs the analyze command, then
              the elaborate command if any, and then the simulate command.

              The GHDL simulator is registered by default, but its registration can be overwritten if required.

   Example: preregistered HDL simulators
       A number of open-source HDL simulators are preregistered in the MyHDL distribution. If they are installed
       in  the  typical  way,  they  are  readily available for conversion verification.  We will illustrate the
       registration process by showing the registrations of these simulators.

       GHDL registration:

          registerSimulator(
              name="GHDL",
              hdl="VHDL",
              analyze="ghdl -a --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd",
              elaborate="ghdl -e --workdir=work -o %(unitname)s_ghdl %(topname)s",
              simulate="ghdl -r %(unitname)s_ghdl"
              )

       Icarus registration:

          registerSimulator(
              name="icarus",
              hdl="Verilog",
              analyze="iverilog -o %(topname)s.o %(topname)s.v",
              simulate="vvp %(topname)s.o"
              )

       cver registration:

          registerSimulator(
              name="cver",
              hdl="Verilog",
              analyze="cver -c -q %(topname)s.v",
              simulate="cver -q %(topname)s.v",
              offset=3
              )

   New modeling features
   New signed() method for intbv
       The intbv object has a new method signed that implements sign extension. The extended bit is the msb  bit
       of the bit representation of the object.

       Clearly,  this  method  only  has  an  effect  for intbv objects whose valid values are a finite range of
       positive integers.

       This method can be converted to VHDL and Verilog.

   always_comb and list of signals
       In the previous MyHDL release, one could use lists of signals in an always_comb block, but they were  not
       considered to infer the sensitivity list. To several users, this was unexpected behavior, or even a bug.

       In  the  present  release, lists of signals are considered and the corresponding signals are added to the
       sensitivity list.  The converter to Verilog and VHDL is adapted accordingly.

   Backwards incompatible changes
   Decorator usage
       The basic building block of a MyHDL design is a specialized Python generator.

       In MyHDL 0.5, decorators were introduced to make it easier to create useful MyHDL  generators.  Moreover,
       they  make the code clearer. As a result, they are now the de facto standard to describe hardware modules
       in MyHDL.

       The  implementation  of  certain  tasks,  such  a  signal  tracing  and  conversion,  can  be  simplified
       significantly  if  decorators  are  used  to  create  the generators. These simplifications have now been
       adopted in the code. This means that decorator usage is assumed.  Legacy code written for  the  mentioned
       purposes without decorators, can always be easily converted into code with decorators.

       For  pure  modeling,  it  doesn't  matter  how generators are created and this will remain so. Therefore,
       designers can continue to experiment with innovative modeling concepts in the fullest generality.

   instances() function
       The instances function can be used to automatically lookup and return the instances that are defined in a
       MyHDL module.  In accordance with the section Decorator usage, its functionality has been  changed.  Only
       generators created by decorators are considered when looking up instances.

   Conversion of printing without a newline
       Printing  without  a  newline  (a  print  statement  followed  by  a comma) is no longer supported by the
       converter to Verilog. This is done to be compatible with the  converter  to  VHDL.  Currently,  the  VHDL
       solution  relies  on  std.textio  and  this  implies  that  printing without a newline cannot be reliably
       converted.

WHAT'S NEW IN MYHDL 0.5

       Author Jan Decaluwe

   Modeling
   Creating generators with decorators
   Introduction
       Python 2.4 introduced a new feature called decorators. A decorator consists of special syntax in front of
       a function declaration.  It  refers  to  a  decorator  function.  The  decorator  function  automatically
       transforms the declared function into some other callable object.

       MyHDL 0.5 defines decorators that can be used to create ready-to-run generators from local functions. The
       use of decorators results in clearer, more explicit code.

   The @instance decorator
       The @instance decorator is the most general decorator in MyHDL.

       In earlier versions of MyHDL, local generator functions are typically used as follows:

          def top(...):
              ...
              def gen_func():
                  <generator body>
              ...
              inst = gen_func()
              ...
              return inst, ...

       Note that the generator function gen_func is intended to be called exactly once, and that its name is not
       necessary  anymore  afterwards.  In  MyHDL  0.5,  this  can  be rewritten as follows, using the @instance
       decorator:

          def top(...):
              ...
              @instance
              def inst():
                  <generator body>
              ...
              return inst, ...

       Behind the curtains, the @instance decorator automatically creates a generator by calling  the  generator
       function,  and  by  reusing  its  name.  Note that it is placed immediately in front of the corresponding
       generator function, resulting in clearer code.

   The @always decorator
       The @always decorator is a specialized decorator that targets a very popular coding pattern. It  is  used
       as follows:

          def top(...):
              ...
              @always(event1, event2, ...)
              def inst()
                  <body>
              ...
              return inst, ...

       The  meaning  of  this code is that the decorated function is executed whenever one of the events occurs.
       The argument list of the decorator corresponds to the  sensitivity  list.  Appropriate  events  are  edge
       specifiers,  signals,  and  delay  objects.  The  decorated  function  is a classic function instead of a
       generator function.

       Behind the curtains, the always decorator creates an enclosing while True loop automatically, and inserts
       a yield statement with the sensitivity list.

   The @always_comb decorator
       The @always_comb decorator is used  to  describe  combinatorial  logic.  It  is  nothing  else  than  the
       always_comb function from earlier MyHDL versions used as a decorator:

          def top(...):
              ...
              @always_comb
              def comb_inst():
                  <combinatorial body>
              ...
              return comb_inst, ...

       The @always_comb decorator infers the inputs of the combinatorial logic and the corresponding sensitivity
       list automatically.

   More information
       For  more  information  about  the  background  and  the design decisions regarding MyHDL decorators, see
       mep-100.

   Recommended style changes
   Decorator usage
       The use of decorators has clear advantages in terms of code clarity. Therefore, it  is  recommended  that
       all local generators be created using decorators.

   Edge specifiers
       Signal  edges  are  typically  specified using the posedge and negedge functions in MyHDL. However, these
       functions are simply wrappers around attributes with the same name. The design decision to use  functions
       have been reviewed and found questionable. In fact, using the attributes directly instead has significant
       advantages, listed in order of increasing significance:

          • one character less to type

          • more object-oriented style

          • less symbols in the myhdl namespace

          • no brackets, which is better for clarity

          • no function call overhead

       From MyHDL 0.5 on, it is therefore recommended to use the edge specifier attributes. For example:

          clk.posedge # instead of posedge(clk)
          rst.negedge # instead of negedge(clk)

   Deprecated features
   Edge specifier functions
       Functions  posedge  and  negedge are deprecated. As discussed before, it is recommended to use the signal
       attributes with the same name instead.

       In MyHDL 0.5, the functions will be removed from all documentation and examples.  They  will  be  removed
       from MyHDL in a future version.

   processes() function
       Function  processes  is  deprecated.  It  looks  up  local  generator  functions and calls them to create
       generators. When MyHDL 0.5 decorators are used as recommended, this functionality becomes superfluous  as
       it is part of the decorator functionality.

       On  the other hand, the companion function instances continues to be relevant and useful. It merely looks
       up instances in a local namespace. Having a single lookup function will also improve usability.

       In MyHDL 0.5, the processes function will be removed from all documentation  and  examples.  It  will  be
       removed from MyHDL in a future version.

   Backwards incompatible changes
   Default initial value of an intbv instance
       It has always been possible to construct an intbv instance without explicit initial value:

          m = intbv()

       Prior to MyHDL 0.4, the default initial value was 0. In MyHDL 0.5, this has been changed to None. This is
       a  first  step towards support for X and Z functionality as found in other HDLs. This may be occasionally
       useful :-) For example, it may be meaningful to initialize memory locations to None  to  make  sure  that
       they  will  not be read before they have been initialized. If None is supported, it seems also logical to
       make it the default initial value, to be interpreted as "No value".

       Warning: if you have calls like the above in your code, it will probably fail with  MyHDL  0.5,  as  many
       integer-like operations are not supported with None values.

       Workaround: change your existing code by using 0 as an explicit initial value, like so:

          m = intbv(0)

   Python version
       Because  of  the  usage of new features such as decorators, MyHDL 0.5 requires upgrading to Python 2.4 or
       higher.

   Verilog conversion
   Decorator support
       The Verilog converter was enhanced to support the proposed decorators.

   Mapping a list of signals to a RAM memory
       Certain synthesis tools can map Verilog memories to memory structures. For example, this is supported  by
       the  Xilinx toolset. To support this interesting feature, the Verilog converter now maps lists of signals
       in MyHDL to Verilog memories.

       The following MyHDL example is a ram model that uses a list of signals to model the internal memory.

          def RAM(dout, din, addr, we, clk, depth=128):
              """  Ram model """

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

              @always(clk.posedge)
              def write():
                  if we:
                      mem[int(addr)].next = din

              @always_comb
              def read():
                  dout.next = mem[int(addr)]

              return write, read

       With the appropriate signal definitions for the interface  ports,  it  is  mapped  by  toVerilog  to  the
       following Verilog code. Note how the list of signals mem is mapped to a Verilog memory.

          module RAM (
              dout,
              din,
              addr,
              we,
              clk
          );

          output [7:0] dout;
          wire [7:0] dout;
          input [7:0] din;
          input [6:0] addr;
          input we;
          input clk;

          reg [7:0] mem [0:128-1];

          always @(posedge clk) begin: _RAM_write
              if (we) begin
                  mem[addr] <= din;
              end
          end

          assign dout = mem[addr];

          endmodule

       Lists  of signals can also be used in MyHDL to elegantly describe iterative hierarchical structures. (See
       the MyHDL manual.) However, there is an important difference: such signals will have a name at some level
       of the hierarchy, while in the case described above, the individual signals are anonymous. The  toVerilog
       converter  detects which case we are in. In the first case, the individual signals will still be declared
       in the Verilog output, using the highest-level hierarchical name. It is only in the second case that  the
       list of signals is declared as a Verilog memory.

   Mapping combinatorial logic to assign statements
       When  possible,  combinatorial  logic  is  now  converted  to  Verilog  assign  statements. There are two
       conditions for this to happen. First, the logic  has  to  be  explicitly  described  as  a  combinatorial
       function  using  the  @always_comb  decorator.  Secondly,  the function has to be simple enough so that a
       mapping to assign statements is possible: only signal assignments are permitted.   Otherwise,  a  Verilog
       always block is used as previously.

       See the RAM model of the previous section for an example.

       This was done because certain synthesis tools require assign statements to recognize code templates.

   Mapping a tuple of integers to a ROM memory
       Some  synthesis  tools,  such as the Xilinx tool, can infer a ROM memory from a case statement. toVerilog
       has been enhanced to do the expansion into a case  statement  automatically,  based  on  a  higher  level
       description.  The  rom  access  is  described in a single line, by indexing into a tuple of integers. The
       tuple can be described manually, but also by programmatical means. Note that a tuple is used instead of a
       list to stress the read-only character of the memory.

       The following example illustrates this functionality.

          def rom(dout, addr, CONTENT):

              @always_comb
              def read():
                  dout.next = CONTENT[int(addr)]

              return read

          dout = Signal(intbv(0)[8:])
          addr = Signal(intbv(0)[4:])
          CONTENT = (17, 134, 52, 9)

          toVerilog(rom, dout, addr, CONTENT)

       The output Verilog code is as follows:

          module rom (
              dout,
              addr
          );

          output [7:0] dout;
          reg [7:0] dout;
          input [3:0] addr;

          always @(addr) begin: _rom_read
              // synthesis parallel_case full_case
              case (addr)
                  0: dout <= 17;
                  1: dout <= 134;
                  2: dout <= 52;
                  default: dout <= 9;
              endcase
          end

          endmodule

   Support for signed arithmetic
       Getting signed representations right in Verilog is tricky. One issue is that a signed  representation  is
       treated  as  a  special  case, and unsigned as the rule.  For example, whenever one of the operands in an
       expression is unsigned, all others are also treated like unsigned. While this is  understandable  from  a
       historical  perspective  (for  backwards  compatibility reasons) it is the opposite from what one expects
       from a high-level point of view, when working with negative numbers. The basic problem is that a  Verilog
       user  has  to deal with representation explicitly in all cases, even for abstract integer operations.  It
       would be much better to leave representational issues to a tool.

       MyHDL doesn't make the distinction between signed and unsigned. The intbv class can handle  any  kind  of
       integer,  including  negative  ones.  If required, you can access the 2's complement representation of an
       intbv object, but for integer operations such a counting, there is no need to worry about this.

       Of course, the Verilog converter has to deal with the representation carefully.  MyHDL  0.4  avoided  the
       issue  by  simply  prohibiting  intbv  objects  with negative values. MyHDL 0.5 adds support for negative
       values and uses the signed Verilog representation to accomplish this.

       The problematic  cases  are  those  when  signed  and  unsigned  representations  are  mixed  in  Verilog
       expressions.  The converter avoids this by making sure that signed arithmetic is used whenever one of the
       operands is signed. Note that this is exactly the opposite of the Verilog default. More specifically, the
       converter may convert an unsigned operand by adding a sign bit and casting to  a  signed  interpretation,
       using  the  Verilog  $signed  function.  Operands  that are treated like this are positive intbv objects,
       slices and subscripts of intbv objects, and bool objects.

       Integer constants are treated as a special case. Unsized integer numbers were always  treated  as  signed
       numbers  in  Verilog. However, as their representation is minimally 32 bits wide, they usually don't give
       problems when mixed with unsigned numbers. Therefore, integer constants don't  cause  signed  casting  of
       other operands in the same expression: users would actually find it surprizing if they did.

   Support for user-defined Verilog code
   Introduction
       In  order  to  provide a path to implementation, MyHDL code can be converted to Verilog. However, in some
       cases the conversion may fail or the result may not be acceptable. For example:

       • conversion will fail if the MyHDL code doesn't follow the rules of the convertible subset

       • a user may want to explicitly instantiate  an  existing  Verilog  module,  instead  of  converting  the
         corresponding MyHDL code

       • it may be necessary to include technology-dependent modules in the Verilog output

       As  a  conclusion,  MyHDL  users need a method to include user-defined Verilog code during the conversion
       process.

   Solution
       MyHDL 0.5 defines a hook that is understood by toVerilog but ignored by the MyHDL simulator. The hook  is
       called  __verilog__.  Its  operation  can  be understood as a special return value. When a MyHDL function
       defines __verilog__, the Verilog converter will use its value instead of the regular return value.

       The value of __verilog__ should be a format string that uses keys in  its  format  specifiers.  The  keys
       refer to the variable names in the context of the string.

       Example:

          def inc_comb(nextCount, count, n):

              @always_comb
              def logic():
                  nextCount.next = (count + 1) % n

              __verilog__ = \
          """
          assign %(nextCount)s = (%(count)s + 1) %% %(n)s;
          """
              nextCount.driven = "wire"

              return logic

       In  this  example,  conversion  of the inc_comb function is bypassed and the user-defined Verilog code is
       inserted instead. Note that the user-defined code refers to signals and parameters in the  MyHDL  context
       by  using  format  specifiers. During conversion, the appropriate hierarchical names and parameter values
       will be filled in. Note also that the format specifier indicator % needs to be escaped (by  doubling  it)
       if it is required in the user-defined code.

       There  is  one  more  issue  that  needs  user  attention. Normally, the Verilog converter infers inputs,
       internal signals, and outputs. It also detects undriven and multiple  driven  signals.  To  do  this,  it
       assumes  that signals are not driven by default. It then processes the code to find out which signals are
       driven from where. However, it cannot do this for user-defined code. Without additional help,  this  will
       result  in warnings or errors during the inference process, or in compilation errors from invalid Verilog
       code. The user should solve this by setting the driven attribute for signals that  are  driven  from  the
       user-defined code. In the example code above, note the following assignment:

          nextCount.driven = "wire"

       This specifies that the nextCount signal is driven as a Verilog wire from this module. The allowed values
       of  the  driven  attribute  are  "wire"  and "reg". The value specifies how the user-defined Verilog code
       drives the signal in Verilog. To decide which value to use, consider how the signal should be declared in
       Verilog after the user-defined code is inserted.

   Limitations
       It is not possible to use the __verilog__ hook in a generator function  -  it  should  be  in  a  classic
       function.  This is because in MyHDL those functions are completely run (elaborated) before the conversion
       starts, while generator functions are not.

   More info
       For more information about the background and the design decisions regarding user-defined  Verilog  code,
       see mep-101.

   Backwards incompatible changes
   Verilog conversion output filename
       A Verilog conversion is performed with a call that looks as follows:

          instance_name = toVerilog(func, ...)

       In  MyHDL  0.4,  the Verilog output filename was called instance_name.v. In MyHDL 0.5, the default output
       filename is func_name.v, where func_name is the name of the function,  available  as  the  func.func_name
       attribute.

       This  was  done  for the following reasons. The MyHDL 0.4 was overly clever and therefore complicated. It
       involves frame handling and parsing the source file for the assignment pattern. Besides being too clever,
       it also had awkward limitations. For example, it was not possible to construct a  dynamic  name  for  the
       instance, which is very un-Pythonic behavior.

       Both  the  implementation  complexity and the limitations are gone with the new behavior: the name of the
       top-level function argument is simply used. In addition, it is now possible  to  specify  a  user-defined
       name for the instance as follows:

          toVerilog.name = "my_name"
          toVerilog(func, ....)

       To support this feature, it was necessary to make toVerilog an instance of a class with a call interface.

       Warning:  When  existing converting code is re-run, the Verilog output filename will be different than in
       0.4.

   Simulation
   Performance optimizations
       To improve the simulation performance of MyHDL, we mainly put our trust  in  Python  development  itself.
       There are good reasons to be optimistic.

       What  MyHDL  itself can do is to minimize the overhead of the simulation loop. In MyHDL 0.5, a first step
       was taken in  this respect.

       MyHDL supports a number of "trigger objects". These are the objects that can occur in  yield  statements,
       for  example  delay, posedge, Signal, and generator objects. Each of these are handled differently and so
       the simulation loop has to account for the  object  type.  Prior  to  MyHDL  0.5,  this  type  check  was
       explicitly  done for each occurrence of a yield statement during simulation. As many generators will loop
       endlessly, it is clear that the same things will  be  checked  over  and  over  again,  resulting  in  an
       important overhead.

       In  MyHDL  0.5,  all generators are predigested. Certain trigger object patterns that tend to occur often
       are given specialized simulation handlers, so  that  continuously  performing  the  same  type  check  is
       avoided. More specifically, they consist of generators that only contain yield statements with a specific
       argument. Currently, 5 different kinds of generators are recognized and accelerated, corresponding to the
       following yield statement arguments:

          • a delay object

          • a Signal object

          • a tuple of Signal objects

          • a posedge or negedge object

          • a tuple of posedge and/or negedge objects

   Backwards incompatible changes
   Waveform tracing output filename
       Waveform tracing is initiated by a call that looks as follows:

          instance_name = traceSignals(func, ...)

       In MyHDL 0.4, the output filename was called instance_name.vcd. In MyHDL 0.5, the default output filename
       is func_name.vcd, where func_name is the name of the function, available as the func.func_name attribute.

       This was done for the same reasons as in the similar case for toVerilog, as described earlier.

       A user-defined name for the output file can be specified as follows:

          traceSignals.name = "my_name"
          inst = traceSignals(func, ....)

       Warning: When existing converting code is re-run, the vcd output filename will be different than in 0.4.

WHAT'S NEW IN MYHDL 0.4: CONVERSION TO VERILOG

       Author Jan Decaluwe

   Introduction
       MyHDL 0.4 supports the automatic conversion of a subset of MyHDL code to synthesizable Verilog code. This
       feature provides a direct path from Python to an FPGA or ASIC implementation.

       MyHDL aims  to be a complete design language, for tasks such as high level modeling and verification, but
       also for implementation. However, prior to 0.4 a user had to translate MyHDL code manually to Verilog  or
       VHDL. Needless to say, this was inconvenient. With MyHDL0.4, this manual step is no longer necessary.

   Solution description
       The  solution  works  as  follows. The hardware description should be modeled in MyHDL style, and satisfy
       certain constraints that are typical for implementation-oriented hardware modeling. Subsequently, such  a
       design is converted to an equivalent model in the Verilog language, using the function toVerilog from the
       MyHDLlibrary.  Finally,  a  third-party  synthesis  tool  is used to convert the Verilog design to a gate
       implementation for an ASIC or FPGA. There are a number of Verilog synthesis tools available,  varying  in
       price, capabilities, and target implementation technology.

       The conversion does not start from source files, but from a design that has been elaborated by the Python
       interpreter. The converter uses the Python profiler to track the interpreter’s operation and to infer the
       design  structure  and  name  spaces.  It  then selectively compiles pieces of source code for additional
       analysis and for conversion. This is done using the Python compiler package.

   Features
   The design is converted after elaboration
       Elaboration refers to the initial processing of a hardware description to achieve a representation  of  a
       design  instance  that  is  ready  for  simulation or synthesis. In particular, structural parameters and
       constructs are processed in this step. In MyHDL, the Python interpreter itself is used for elaboration. A
       Simulation object is constructed with elaborated design instances as  arguments.  Likewise,  the  Verilog
       conversion  works  on  an  elaborated  design  instance.  The  Python interpreter is thus used as much as
       possible.

   The structural description can be arbitrarily complex and hierarchical
       As the conversion works on an elaborated design instance, any modeling constraints only apply to the leaf
       elements of the design structure, that is, the co-operating generators. In  other  words,  there  are  no
       restrictions  on  the  description  of  the  design  structure:  Python’s full power can be used for that
       purpose. Also, the design hierarchy can be arbitrarily deep.

   Generators are mapped to Verilog always or initial blocks
       The converter analyzes the code of each generator and maps it to a Verilog always blocks if possible, and
       to an initial block otherwise. The converted Verilog design will be a flat “net list of blocks”.

   The Verilog module interface is inferred from signal usage
       In MyHDL, the input or output direction of interface signals is not explicitly  declared.  The  converter
       investigates  signal usage in the design hierarchy to infer whether a signal is used as input, output, or
       as an internal signal. Internal signals are given a hierarchical name in the Verilog output.

   Function calls are mapped to a unique Verilog function or task call
       The converter analyzes function calls and function code to see  if  they  should  be  mapped  to  Verilog
       functions  or  to  tasks.  Python functions are much more powerful than Verilog subprograms; for example,
       they are inherently generic, and they can be called with named association.  To  support  this  power  in
       Verilog, a unique Verilog function or task is generated per Python function call.

   If-then-else structures may be mapped to Verilog case statements
       Python  does  not  provide a case statement. However, the converter recognizes if-then-else structures in
       which a variable is sequentially compared to items of an enumeration type, and maps such a structure to a
       Verilog case statement with the appropriate synthesis attributes.

   Choice of encoding schemes for enumeration types
       The enum function in MyHDL returns an enumeration type.  This  function  takes  an  additional  parameter
       encoding  that  specifies  the desired encoding in the implementation: binary, one hot, or one cold.  The
       Verilog converter generates the appropriate code.

   The convertible subset
   Introduction
       Unsurprisingly, not all MyHDL code can be converted  to  Verilog.  In  fact,  there  are  very  important
       restrictions.  As  the  goal  of the conversion functionality is implementation, this should not be a big
       issue: anyone familiar with synthesis is used to similar restrictions  in  the  synthesizable  subset  of
       Verilog  and  VHDL.  The  converter attempts to issue clear error messages when it encounters a construct
       that cannot be converted.

       In practice, the synthesizable subset usually refers to RTL synthesis, which is by far the  most  popular
       type  of  synthesis  today.  There  are industry standards that define the RTL synthesis subset. However,
       those were not used as a model for the restrictions of the MyHDL converter, but  as  a  minimal  starting
       point.  On  that  basis, whenever it was judged easy or useful to support an additional feature, this was
       done. For example, it is actually easier to convert while loops than for loops even though they  are  not
       RTL-synthesizable.  As  another  example,  print  is supported because it’s so useful for debugging, even
       though it’s not synthesizable. In summary, the convertible subset is  a  superset  of  the  standard  RTL
       synthesis  subset,  and  supports  synthesis  tools  with  more advanced capabilities, such as behavioral
       synthesis.

       Recall that any restrictions only apply to the design post elaboration.  In  practice,  this  means  that
       they apply only to the code of the generators, that are the leaf functional blocks in a MyHDL design.

   Coding style
       A  natural  restriction  on  convertible  code  is  that it should be written in MyHDL style: cooperating
       generators, communicating through signals, and with yield statements specifying wait  points  and  resume
       conditions.  Supported  resume  conditions  are  a  signal  edge,  a  signal  change,  or a tuple of such
       conditions.

   Supported types
       The most important restriction regards object types. Verilog is an almost typeless language, while Python
       is strongly (albeit dynamically) typed. The converter has to infer the types of names used in  the  code,
       and map those names to Verilog variables.

       Only  a  limited  amount  of  types  can  be converted. Python int and long objects are mapped to Verilog
       integers. All other supported types are mapped to Verilog regs (or wires), and therefore need to  have  a
       defined  bit  width.  The  supported  types  are  the  Python  bool type, the MyHDL intbv type, and MyHDL
       enumeration types returned by function enum. The latter objects can also be used as the base object of  a
       Signal.

       intbv  objects  must  be  constructed so that a bit width can be inferred. This can be done by specifying
       minimum and maximum values, e.g. as follows:

          index = intbv(0, min=0, max=2**N)

       Alternatively, a slice can be taken from an intbv object as follows:

          index = intbv(0)[N:]

       Such as slice returns a new intbv object, with minimum value 0 , and maximum value 2**N.

   Supported statements
       The following is a list of the statements that are supported by the Verilog converter, possibly qualified
       with restrictions or usage notes.

       The break statement.

       The continue statement.

       The def statement.

       The for statement.
              The only supported iteration scheme  is  iterating  through  sequences  of  integers  returned  by
              built-in function range or MyHDLfunction downrange. The optional else clause is not supported.

       The if statement.
              if, elif, and else clauses are fully supported.

       The pass statement.

       The print statement.
              When  printing  an  interpolated  string, the format specifiers are copied verbatim to the Verilog
              output. Printing to a file (with syntax ’>>’) is not supported.

       The raise statement.
              This statement is mapped to Verilog statements that end the simulation with an error message.

       The return statement.

       The yield statement.
              The yielded expression can be a signal, a signal edge as specified by MyHDL functions  posedge  or
              negedge, or a tuple of signals and edge specifications.

       The while statement.
              The optional else clause is not supported.

   Methodology notes
   Simulation
       In  the  Python  philosophy,  the  run-time rules. The Python compiler doesn’t attempt to detect a lot of
       errors beyond syntax errors, which given Python’s ultra-dynamic nature would be an almost impossible task
       anyway. To verify a Python program, one should run it, preferably  using  unit  testing  to  verify  each
       feature.

       The  same  philosophy  should  be  used  when  converting  a  MyHDL description to Verilog: make sure the
       simulation runs fine first. Although the converter checks many things and attempts to issue  clear  error
       messages, there is no guarantee that it does a meaningful job unless the simulation runs fine.

   Conversion output verification
       It is always prudent to verify the converted Verilog output. To make this task easier, the converter also
       generates  a  test  bench  that  makes  it  possible  to  simulate  the  Verilog design using the Verilog
       co-simulation interface. This permits one to verify the Verilog code with the same test  bench  used  for
       the MyHDL code. This is also how the Verilog converter development is being verified.

   Assignment issues
   Name assignment in Python
       Name  assignment  in  Python  is  a  different  concept  than in many other languages. This point is very
       important for effective modeling in Python, and even more so for synthesizable MyHDL code. Therefore, the
       issues are discussed here explicitly.

       Consider the following name assignments:

          a = 4
          a = ``a string''
          a = False

       In many languages, the meaning would be that an existing variable a gets a number of different values. In
       Python, such a concept of a variable doesn’t exist. Instead, assignment merely creates a new binding of a
       name to a certain object, that replaces any previous binding. So in the example, the name a  is  bound  a
       number of different objects in sequence.

       The  Verilog  converter  has  to investigate name assignment and usage in MyHDL code, and to map names to
       Verilog variables. To achieve that, it tries to infer the  type  and  possibly  the  bit  width  of  each
       expression that is assigned to a name.

       Multiple assignments to the same name can be supported if it can be determined that a consistent type and
       bit  width  is  being  used  in  the  assignments.  This  can  be  done  for boolean expressions, numeric
       expressions, and enumeration type literals. In Verilog, the corresponding name is mapped to a single  bit
       reg, an integer, or a reg with the appropriate width, respectively.

       In  other  cases,  a single assignment should be used when an object is created. Subsequent value changes
       are then achieved by modification of an existing object. This technique should be  used  for  Signal  and
       intbv objects.

   Signal assignment
       Signal assignment in MyHDL is implemented using attribute assignment to attribute next. Value changes are
       thus  modeled  by  modification  of  the existing object. The converter investigates the Signal object to
       infer the type and bit width of the corresponding Verilog variable.

   intbv objects
       Type intbv is likely to be the workhorse for synthesizable modeling in MyHDL. An intbv  instance  behaves
       like  a  (mutable)  integer  whose  individual bits can be accessed and modified. Also, it is possible to
       constrain its set of values. In addition to error checking, this makes it possible to infer a bit  width,
       which is required for implementation.

       In  Verilog,  an intbv instance will be mapped to a reg with an appropriate width. As noted before, it is
       not possible to modify its value using name assignment. In the following, we will show how it can be done
       instead. Consider:

          a = intbv(0)[8:]

       This is an intbv object with initial value 0 and bit width 8. The change its value to 5, we can use slice
       assignment:

          a[8:] = 5

       The same can be achieved by leaving the bit width unspecified, which has  the  meaning  to  change  “all”
       bits:

          a[:] = 5

       Often  the  new  value  will depend on the old one. For example, to increment an intbv with the technique
       above:

          a[:] = a + 1

       Python also provides augmented assignment operators, which can be used to implement in-place  operations.
       These  are  supported  on  intbv  objects and by the converter, so that the increment can also be done as
       follows:

          a += 1

   Converter usage
       We will demonstrate the conversion process by showing some examples.

   A small design with a single generator
       Consider the following MyHDL code for an incrementer module:

          def inc(count, enable, clock, reset, n):
              """ Incrementer with enable.

              count -- output
              enable -- control input, increment when 1
              clock -- clock input
              reset -- asynchronous reset input
              n -- counter max value
              """
              def incProcess():
                  while 1:
                      yield posedge(clock), negedge(reset)
                      if reset == ACTIVE_LOW:
                          count.next = 0
                      else:
                          if enable:
                              count.next = (count + 1) % n
              return incProcess()

       In Verilog terminology, function inc corresponds to a module, while generator function incProcess roughly
       corresponds to an always block.

       Normally, to simulate the design, we would “elaborate” an instance as follows:

          m = 8
          n = 2 ** m

          count = Signal(intbv(0)[m:])
          enable = Signal(bool(0))
          clock, reset = [Signal(bool()) for i in range(2)]

          inc_inst = inc(count, enable, clock, reset, n=n)

       incinst is an elaborated design instance that can be simulated. To convert it to Verilog, we  change  the
       last line as follows:

          inc_inst = toVerilog(inc, count, enable, clock, reset, n=n)

       Again,  this  creates  an  instance  that  can  be  simulated, but as a side effect, it also generates an
       equivalent Verilog module in file . The Verilog code looks as follows:

          module inc_inst (
              count,
              enable,
              clock,
              reset
          );

          output [7:0] count;
          reg [7:0] count;
          input enable;
          input clock;
          input reset;

          always @(posedge clock or negedge reset) begin: _MYHDL1_BLOCK
              if ((reset == 0)) begin
                  count <= 0;
              end
              else begin
                  if (enable) begin
                      count <= ((count + 1) % 256);
                  end
              end
          end

          endmodule

       You can see the module interface and the always block, as expected from the MyHDL design.

   Converting a generator directly
       It is also possible to convert a generator  directly.  For  example,  consider  the  following  generator
       function:

          def bin2gray(B, G, width):
              """ Gray encoder.

              B -- input intbv signal, binary encoded
              G -- output intbv signal, gray encoded
              width -- bit width
              """
              Bext = intbv(0)[width+1:]
              while 1:
                  yield B
                  Bext[:] = B
                  for i in range(width):
                      G.next[i] = Bext[i+1] ^ Bext[i]

       As before, you can create an instance and convert to Verilog as follows:

          width = 8

          B = Signal(intbv(0)[width:])
          G = Signal(intbv(0)[width:])

          bin2gray_inst = toVerilog(bin2gray, B, G, width)

       The generated Verilog code looks as follows:

          module bin2gray_inst (
              B,
              G
          );

          input [7:0] B;
          output [7:0] G;
          reg [7:0] G;

          always @(B) begin: _MYHDL1_BLOCK
              integer i;
              reg [9-1:0] Bext;
              Bext[9-1:0] = B;
              for (i=0; i<8; i=i+1) begin
                  G[i] <= (Bext[(i + 1)] ^ Bext[i]);
              end
          end

          endmodule

   A hierarchical design
       The hierarchy of convertible designs can be arbitrarily deep.

       For  example,  suppose  we  want  to  design an incrementer with Gray code output. Using the designs from
       previous sections, we can proceed as follows:

          def GrayInc(graycnt, enable, clock, reset, width):

              bincnt = Signal(intbv()[width:])

              INC_1 = inc(bincnt, enable, clock, reset, n=2**width)
              BIN2GRAY_1 = bin2gray(B=bincnt, G=graycnt, width=width)

              return INC_1, BIN2GRAY_1

       According to Gray code properties, only a single bit will change in consecutive values. However,  as  the
       bin2gray  module  is  combinatorial,  the  output  bits  may  have  transient  glitches, which may not be
       desirable. To solve this, let’s create an additional level of hierarchy and add an output register to the
       design. (This will create an additional latency of a clock cycle, which may not  be  acceptable,  but  we
       will ignore that here.)

          def GrayIncReg(graycnt, enable, clock, reset, width):

              graycnt_comb = Signal(intbv()[width:])

              GRAY_INC_1 = GrayInc(graycnt_comb, enable, clock, reset, width)

              def reg():
                  while 1:
                      yield posedge(clock)
                      graycnt.next = graycnt_comb
              REG_1 = reg()

              return GRAY_INC_1, REG_1

       We can convert this hierarchical design as before:

          width = 8
          graycnt = Signal(intbv()[width:])
          enable, clock, reset = [Signal(bool()) for i in range(3)]

          GRAY_INC_REG_1 = toVerilog(GrayIncReg, graycnt, enable, clock, reset, width)

       The Verilog output code looks as follows:

          module GRAY_INC_REG_1 (
              graycnt,
              enable,
              clock,
              reset
          );

          output [7:0] graycnt;
          reg [7:0] graycnt;
          input enable;
          input clock;
          input reset;

          reg [7:0] graycnt_comb;
          reg [7:0] _GRAY_INC_1_bincnt;

          always @(posedge clock or negedge reset) begin: _MYHDL1_BLOCK
              if ((reset == 0)) begin
                  _GRAY_INC_1_bincnt <= 0;
              end
              else begin
                  if (enable) begin
                      _GRAY_INC_1_bincnt <= ((_GRAY_INC_1_bincnt + 1) % 256);
                  end
              end
          end

          always @(_GRAY_INC_1_bincnt) begin: _MYHDL4_BLOCK
              integer i;
              reg [9-1:0] Bext;
              Bext[9-1:0] = _GRAY_INC_1_bincnt;
              for (i=0; i<8; i=i+1) begin
                  graycnt_comb[i] <= (Bext[(i + 1)] ^ Bext[i]);
              end
          end

          always @(posedge clock) begin: _MYHDL9_BLOCK
              graycnt <= graycnt_comb;
          end

          endmodule

       Note  that the output is a flat “net list of blocks”, and that hierarchical signal names are generated as
       necessary.

   Optimizations for finite state machines
       As often in hardware design, finite state machines deserve special attention.

       In Verilog and VHDL, finite state machines are typically described using case statements. Python  doesn’t
       have  a  case statement, but the converter recognizes particular if-then-else structures and maps them to
       case statements. This  optimization  occurs  when  a  variable  whose  type  is  an  enumerated  type  is
       sequentially  tested  against  enumeration  items  in  an  if-then-else  structure. Also, the appropriate
       synthesis pragmas for efficient synthesis are generated in the Verilog code.

       As a further optimization, function enum was enhanced to support alternative encoding schemes  elegantly,
       using an additional parameter encoding. For example:

          t_State = enum('SEARCH', 'CONFIRM', 'SYNC', encoding='one_hot')

       The default encoding is ’binary’; the other possibilities are ’onehot’ and ’onecold’. This parameter only
       affects  the  conversion  output,  not  the  behavior  of  the  type. The generated Verilog code for case
       statements is optimized for an efficient implementation according to the encoding. Note that in contrast,
       a Verilog designer has to make nontrivial code changes to implement a different encoding scheme.

       As an example, consider the following finite state machine, whose state  variable  uses  the  enumeration
       type defined above:

          FRAME_SIZE = 8

          def FramerCtrl(SOF, state, syncFlag, clk, reset_n):

              """ Framing control FSM.

              SOF -- start-of-frame output bit
              state -- FramerState output
              syncFlag -- sync pattern found indication input
              clk -- clock input
              reset_n -- active low reset

              """

              index = intbv(0, min=0, max=8) # position in frame
              while 1:
                  yield posedge(clk), negedge(reset_n)
                  if reset_n == ACTIVE_LOW:
                      SOF.next = 0
                      index[:] = 0
                      state.next = t_State.SEARCH
                  else:
                      SOF.next = 0
                      if state == t_State.SEARCH:
                          index[:] = 0
                          if syncFlag:
                              state.next = t_State.CONFIRM
                      elif state == t_State.CONFIRM:
                          if index == 0:
                              if syncFlag:
                                  state.next = t_State.SYNC
                              else:
                                  state.next = t_State.SEARCH
                      elif state == t_State.SYNC:
                          if index == 0:
                              if not syncFlag:
                                  state.next = t_State.SEARCH
                          SOF.next = (index == FRAME_SIZE-1)
                      else:
                          raise ValueError("Undefined state")
                      index[:]= (index + 1) % FRAME_SIZE

       The conversion is done as before:

          SOF = Signal(bool(0))
          syncFlag = Signal(bool(0))
          clk = Signal(bool(0))
          reset_n = Signal(bool(1))
          state = Signal(t_State.SEARCH)
          framerctrl_inst = toVerilog(FramerCtrl, SOF, state, syncFlag, clk, reset_n)

       The Verilog output looks as follows:

          module framerctrl_inst (
              SOF,
              state,
              syncFlag,
              clk,
              reset_n
          );
          output SOF;
          reg SOF;
          output [2:0] state;
          reg [2:0] state;
          input syncFlag;
          input clk;
          input reset_n;

          always @(posedge clk or negedge reset_n) begin: _MYHDL1_BLOCK
              reg [3-1:0] index;
              if ((reset_n == 0)) begin
                  SOF <= 0;
                  index[3-1:0] = 0;
                  state <= 3'b001;
              end
              else begin
                  SOF <= 0;
                  // synthesis parallel_case full_case
                  casez (state)
                      3'b??1: begin
                          index[3-1:0] = 0;
                          if (syncFlag) begin
                              state <= 3'b010;
                          end
                      end
                      3'b?1?: begin
                          if ((index == 0)) begin
                              if (syncFlag) begin
                                  state <= 3'b100;
                              end
                              else begin
                                  state <= 3'b001;
                              end
                          end
                      end
                      3'b1??: begin
                          if ((index == 0)) begin
                              if ((!syncFlag)) begin
                                  state <= 3'b001;
                              end
                          end
                          SOF <= (index == (8 - 1));
                      end
                      default: begin
                          $display("Verilog: ValueError(Undefined state)");
                          $finish;
                      end
                  endcase
                  index[3-1:0] = ((index + 1) % 8);
              end
          end
          endmodule

   Known issues
       Negative values of intbv instances are not supported.
              The intbv class is quite capable of representing negative values. However, the signed type support
              in  Verilog is relatively recent and mapping to it may be tricky. In my judgment, this was not the
              most urgent requirement, so I decided to leave this for later.

       Verilog integers are 32 bit wide
              Usually, Verilog integers are 32 bit wide. In contrast, Python  is  moving  toward  integers  with
              undefined width. Python int and long variables are mapped to Verilog integers; so for values wider
              than 32 bit this mapping is incorrect.

       Synthesis pragmas are specified as Verilog comments.
              The  recommended  way to specify synthesis pragmas in Verilog is through attribute lists. However,
              my Verilog simulator (Icarus) doesn’t support them for case statements  (to  specify  parallelcase
              and  fullcase pragmas). Therefore, I still used the old but deprecated method of synthesis pragmas
              in Verilog comments.

       Inconsistent place of the sensitivity list inferred from alwayscomb.
              The semantics of alwayscomb, both in Verilog and MyHDL, is to have an implicit sensitivity list at
              the end of the code. However, this may not be synthesizable. Therefore, the  inferred  sensitivity
              list  is put at the top of the corresponding always block. This may cause inconsistent behavior at
              the start of the simulation. The workaround is to create events at time 0.

       Non-blocking assignments to task arguments don’t work.
              I didn’t get non-blocking (signal) assignments to task arguments to work. I don’t know yet whether
              the issue is my own, a Verilog issue, or an issue with my Verilog simulator Icarus. I’ll  need  to
              check this further.

WHAT’S NEW IN MYHDL 0.3

       Author Jan Decaluwe

   VCD output for waveform viewing
       [image: image] [image]

       MyHDL now  has  support  for  waveform viewing. During simulation, signal changes can be written to a VCD
       output file that can be loaded into a waveform viewer tool such as gtkwave.

       The user interface of this feature consists of a single function, traceSignals. To explain how it  works,
       recall  that  in  MyHDL, an instance is created by assigning the result of a function call to an instance
       name. For example:

          tb_fsm = testbench()

       To enable VCD tracing, the instance should be created as follows instead:

          tb_fsm = traceSignals(testbench)

       All signals in the instance hierarchy will be traced in a VCD file called . Note that first the  argument
       of  traceSignals  consists  of  the  uncalled  function.  By  calling  the  function  under  its control,
       traceSignals gathers information about the hierarchy and the signals to  be  traced.  In  addition  to  a
       function  argument,  traceSignals  accepts  an arbitrary number of non-keyword and keyword arguments that
       will be passed to the function call.

       Signals are dumped in a suitable format. This format is inferred at the Signal  construction  time,  from
       the  type  of the initial value.  In particular, bool signals are dumped as single bits. (This only works
       starting with Python 2.3, when bool has become a separate type). Likewise, intbv signals with  a  defined
       bit  width are dumped as bit vectors. To support the general case, other types of signals are dumped as a
       string representation, as returned by the standard str function.

       [warning] Support for literal string representations is not part of the VCD standard. It is  specific  to
       gtkwave. To generate a standard VCD file, you need to use signals with a defined bit width only.

   Enumeration types
       It  is  often  desirable  to  define a set of identifiers. A standard Python idiom for this purpose is to
       assign a range of integers to a tuple of identifiers, like so:

          >>> SEARCH, CONFIRM, SYNC = range(3)
          >>> CONFIRM
          1

       However, this technique has some drawbacks. Though it is  clearly  the  intention  that  the  identifiers
       belong  together, this information is lost as soon as they are defined. Also, the identifiers evaluate to
       integers, whereas a string representation of the identifiers would be preferable.  To solve these issues,
       we need an enumeration type.

       MyHDL 0.3 supports enumeration types by providing a function enum. The arguments to enum are  the  string
       representations  of  the  identifiers,  and  its return value is an enumeration type. The identifiers are
       available as attributes of the type. For example:

          >>> from myhdl import enum
          >>> t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
          >>> t_State
          <Enum: SEARCH, CONFIRM, SYNC>
          >>> t_State.CONFIRM
          CONFIRM

       Enumeration types are often used for the state variable in a finite state machine.  In  the  waveform  in
       Section 1,  you  see  a Signal called state. Note how the waveforms show the string representation of the
       enumeration type identifiers The state signal has been constructed with an enumeration type identifier as
       its initial value, as follows:

          state = Signal(t_State.SEARCH)

   Inferring the sensitivity list for combinatorial logic
       In MyHDL, combinatorial logic is described by a generator function with a sensitivity list that  contains
       all inputs signals (the signals that are read inside the function).

       It  may  be  easy  to  forget some input signals, especially it there are a lot of them or if the code is
       being modified. There are various ways to solve this. One way is to use a sophisticated  editor.  Another
       way  is  direct  language  support. For example, recent versions of Verilog have the always @* construct,
       that infers all input signals. The  SystemVerilog 3.1  standard  improves  on  this  by  introducing  the
       always_comb block with slightly enhanced semantics.

       MyHDL 0.3  provides  a  function  called  always_comb  which is named and modeled after the SystemVerilog
       counterpart.  always_comb takes a classic local function as its argument.  This function  should  specify
       the  combinatorial  logic behavior.  always_comb returns a generator that is sensitive to all inputs, and
       that will run the function whenever an input changes.

       For example, suppose that we have a mux module described as follows:

          def mux(z, a, b, sel):
              """ Multiplexer.

              z -- mux output
              a, b -- data inputs
              sel -- control input

              """
              def logic()
                  while 1:
                      yield a, b, sel
                      if sel == 1:
                          z.next = a
                      else:
                          z.next = b
              mux_logic = logic()
              return mux_logic

       Using always_comb, we can describe it as follows instead:

          def mux(z, a, b, sel):
              """ Multiplexer.

              z -- mux output
              a, b -- data inputs
              sel -- control input

              """
              def logic()
                  if sel == 1:
                      z.next = a
                  else:
                      z.next = b
              mux_logic = always_comb(logic)
              return mux_logic

       Note that in the first version, the sensitivity list is at the beginning of the generator function  code.
       This  is traditionally done in synthesizable RTL style modeling. However, the semantics of this style are
       not entirely correct: at the start of the simulation, the  combinatorial  output  will  not  reflect  the
       initial  state  of the inputs.  always_comb solves this by putting the sensitivity list at the end of the
       code.

   Inferring the list of instances
       In MyHDL, the instances defined in a top level function need to be returned explicitly. The following  is
       a schematic example:

          def top(...):
              ...
              instance_1 = module_1(...)
              instance_2 = module_2(...)
              ...
              instance_n = module_n(...)
              ...
              return instance_1, instance_2, ... , instance_n

       It  may  be  convenient  to  assemble  the  list of instances automatically, especially if there are many
       instances. For this purpose, MyHDL 0.3 provides the function instances. It is used as follows:

          from myhdl import instances

          def top(...):
              ...
              instance_1 = module_1(...)
              instance_2 = module_2(...)
              ...
              instance_n = module_n(...)
              ...
              return instances()

       Function instances uses introspection to inspect the type of the local variables defined by  the  calling
       function.  All variables that comply with the definition of an instance are assembled in a list, and that
       list is returned.

   Inferring the list of processes
       In addition to instances, a top level function may also define local generators functions, which  I  will
       call  processes  because  of  the  analogy  with  VHDL.  Like  instances,  processes  need to be returned
       explicitly, with the qualification that they have to be called first to turn them  into  generators.  The
       following is a schematic example:

          def top(...):
              ...
              def process_1():
                  ...
              def process_2():
                  ...
              ...
              def process_n():
                  ...
              ...
              return process_1(), process_2(), ..., process_n()

       As  for  instances, it may be more convenient to assemble the list of processes automatically. One option
       is to turn each process into an instance by calling it and assigning the returned generator  to  a  local
       variable. Those instances will then be found by the instances function described in Section 4.

       Another  option  is to use the function processes provided by MyHDL 0.3. This function uses introspection
       to find the processes, calls each of them, and assembles the returned generators into a list. It  can  be
       used as follows:

          from myhdl import processes

          def top(...):
              ...
              def process_1():
                  ...
              def process_2():
                  ...
              ...
              def process_n():
                  ...
              ...
              return processes()

       To  conclude, a top level function with both instances and processes can use the following idiomatic code
       to return all of them:

          return instances(), processes()

   Class intbv enhancements
       Class intbv has been enhanced with new features.

       It is now possible to leave the left index of a slicing operation unspecified. The meaning is  to  access
       “all” higher order bits. For example:

          >>> from myhdl import intbv
          >>> n = intbv()
          >>> hex(n)
          '0x0'
          >>> n[:] = 0xde
          >>> hex(n)
          '0xde'
          >>> n[:8] = 0xfa
          >>> hex(n)
          '0xfade'
          >>> n[8:] = 0xb4
          >>> hex(n)
          '0xfab4'

       intbv  objects now have min and max attributes that can be specified at construction time. The meaning is
       that only values within range(min, max) are permitted. The default value for these  attributes  is  None,
       meaning “infinite”. For example (traceback output shortened for clarity):

          >>> n = intbv(min=-17, max=53)
          >>> n
          intbv(0)
          >>> n.min
          -17
          >>> n.max
          53
          >>> n[:] = 28
          >>> n
          intbv(28)
          >>> n[:] = -18
          Traceback (most recent call last):
              ....
          ValueError: intbv value -18 < minimum -17
          >>> n[:] = 53
          Traceback (most recent call last):
              ....
          ValueError: intbv value 53 >= maximum 53

       When  a  slice  is  taken from an intbv object, the return value is a new intbv object with a defined bit
       width. As in Verilog, the value of the new intbv object is always positive, regardless of the sign of the
       original value. In addition, the min and max attributes are set implicitly:

          >>> v = intbv()[6:]
          >>> v
          intbv(0)
          >>> v.min
          0
          >>> v.max
          64

       Lastly, a small change was implemented with regard to binary  operations.   In  previous  versions,  both
       numeric  and  bit-wise  operations always returned a new intbv object, even in mixed-mode operations with
       int objects. This has changed: numeric operations return an int, and bitwise operations return  a  intbv.
       In this way, the return value corresponds better to the nature of the operation.

   Function concat
       In  previous  versions,  the  intbv class provided a method. This method is no longer available. Instead,
       there is now a concat function that supports a much broader range of objects.

       A function is more natural because MyHDL objects of various types can be concatenated: intbv objects with
       a defined bit width, bool objects, the corresponding signal objects, and bit strings. All  these  objects
       have  a  defined bit width. Moreover, the first argument doesn’t need to have a defined bit width. It can
       also be an unsized intbv, an int, a long, or a corresponding signal object. Function  concat  returns  an
       intbv object.

   Python 2.3 support
       Python 2.3 was released on July 29, 2003, and as of this writing, it is the latest stable Python release.
       MyHDL 0.3  works with both Python 2.2 and Python 2.3. In good Python tradition, MyHDL code developed with
       Python 2.2 should run without changes or problems in Python 2.3.

       In general, I am not that keen on early upgrading. However,  as  it  happens,  the  evolution  of  Python
       enables  features  that are really important or even crucial to MyHDL. Python 2.2 generators are the best
       example: they are the cornerstone of MyHDL. But Python 2.3 also has significant benefits,  which  I  will
       summarize below.

       First,  generators  and  the yield statement are a default Python 2.3 feature. This means that statements
       are no longer required.

       Second, Python 2.3 has a bool type, which is implemented as a subtype of int. For general Python use, the
       implications are rather limited - the main difference is that logical result values will print  as  False
       and True instead of 0 and 1. However, in MyHDL, I can use the bool type to infer a bit width. If a Signal
       is  constructed  with  a bool value, it is a single bit Signal. One application is waveform viewing as in
       Section 1 In the waveform, note how single bit signals are displayed as level changes. With  Python  2.2,
       the waveforms of these signals would only show value changes, which is not as clear for single bits.

       Finally,  Python 2.3 is significantly faster. MyHDL code runs 25–35% faster in Python 2.3. This is a very
       nice speedup compared to the small burden of a straightforward upgrade.

       Python is a very stable language, so upgrading to Python 2.3 is virtually risk free. Given the additional
       benefits, I recommend MyHDL users to do so as soon as possible. For the next major MyHDLrelease, the  new
       features will become required and only Python 2.3 (and higher) will be supported.

       • genindex

       • search

AUTHOR

       Jan Decaluwe

COPYRIGHT

       2019, Jan Decaluwe

                                                October 18, 2019                                        MYHDL(1)