\chapter{Introduction to \myhdl\ } \section{A basic \myhdl\ simulation} We will introduce \myhdl\ with a classical \code{Hello World} style example. Here are the contents of a \myhdl\ simulation script called \file{hello1.py}: \begin{verbatim} from myhdl import delay, now, Simulation def sayHello(): while 1: yield delay(10) print "%s Hello World!" % now() gen = sayHello() sim = Simulation(gen) sim.run(30) \end{verbatim} When we run this simulation, we get the following output: \begin{verbatim} % python hello1.py 10 Hello World! 20 Hello World! 30 Hello World! StopSimulation: Simulated for duration 30 \end{verbatim} The first line of the script imports a number of objects from the \code{myhdl} package. In good Python style, and unlike most other languages, we can only use identifiers that are \emph{literally} defined in the source file \footnote{I don't want to explain the \samp{import *} syntax}. Next, we define a generator function called \code{sayHello}. This is a generator function (as opposed to a classic Python function) because it contains a \keyword{yield} statement (instead of \keyword{return} statement). In \myhdl\, a \keyword{yield} statement has a similar purpose as a \keyword{wait} statement in VHDL: the statement suspends execution of the function, and its clauses specify when the function should resume. In this case, there is a \code{delay} clause, that specifies the required delay. To make sure that the generator runs ``forever'', we wrap its behavior in a \code{while 1} loop. This is a standard Python idiom, and it is the \myhdl\ equivalent of the implicit looping behavior of a Verilog \keyword{always} block and a VHDL \keyword{process}. In \myhdl\, the basic simulation objects are generators. Generators are created by calling generator functions. For example, variable \code{gen} refers to a generator. To simulate this generator, we pass it as an argument to a \class{Simulation} object constructor. We then run the simulation for the desired amount of time. In \myhdl\, time is modeled by a natural integer. \section{Concurrent generators and signals} In the previous section, we simulated a single generator. Of course, real hardware descriptions are not like that: in fact, they are typically massively concurrent. \myhdl\ supports this by allowing an arbitrary number of concurrent generators. More specifically, a \class{Simulation} constructor can take an arbitrary number of arguments, each of which can be a generator or a nested sequence of generators. With concurrency comes the problem of deterministic communication. Therefore, hardware languages use special objects to support deterministic communication between concurrent code. \myhdl\ has as \class{Signal} object which is roughly modeled after VHDL signals. We will demonstrate these concepts by extending and modifying our first example. We introduce a clock signal, driven by a second generator: \begin{verbatim} clk = Signal(0) def clkGen(): while 1: yield delay(10) clk.next = 1 yield delay(10) clk.next = 0 \end{verbatim} The \code{clk} signal is constructed with an initial value \code{0}. In the clock generator function \code{clkGen}, it is continuously assigned a new value after a certain delay. In \myhdl{}, the new value of a signal is specified by assigning to its \code{next} attribute. This is the \myhdl\ equivalent of VHDL signal assignments and Verilog's non-blocking assignments. The \code{sayHello} generator function is modified to wait for a rising edge of the clock instead of a delay: \begin{verbatim} def sayHello(): while 1: yield posedge(clk) print "%s Hello World!" % now() \end{verbatim} Waiting for a clock edge is achieved with a second form of the \keyword{yield} statement: \samp{yield posedge(\var{signal})}. A \class{Simulation} object will suspend the generator as that point, and resume it when there is a rising edge on the signal. The \class{Simulation} is now constructed with 2 generator arguments: \begin{verbatim} sim = Simulation(clkGen(), sayHello()) sim.run(50) \end{verbatim} When we run this simulation, we get: \begin{verbatim} % python hello2.py 10 Hello World! 30 Hello World! 50 Hello World! StopSimulation: Simulated for duration 50 \end{verbatim} \section{Parameters, instantiations and hierarchy} So far, the generator function examples had no parameters. For example, the \code{clk} signal was defined in the enclosing scope of the generator functions. However, to make the code reusable we will want to pass arguments through a parameter list. For example, we can change the clock generator function to make it more general and reusable, as follows: \begin{verbatim} def clkGen(clock, period=20): lowTime = int(period / 2) highTime = period - lowTime while 1: yield delay(lowTime) clock.next = 1 yield delay(highTime) clock.next = 0 \end{verbatim} The clock signal is now a parameter of the function. Also, the clock \var{period} is a parameter with a default value of \code{20}. This makes \var{period} an \dfn{optional} parameter; if it is not specified in a call, the default value will be used. Similarly, the \code{sayHello} function can be made more general: \begin{verbatim} def sayHello(clock, to="World!"): while 1: yield posedge(clock) print "%s Hello %s" % (now(), to) \end{verbatim} We can create any number of generators by calling generator functions with the appropriate parameters. This is very similar to the concept of \dfn{instantiation} in hardware description languages and we will use the same terminology in \myhdl{}. Hierarchy can be modeled by defining the instances in a higher-level function, and returning them. For example: \begin{verbatim} def greetings(): clk1 = Signal(0) clk2 = Signal(0) clkGen1 = clkGen(clk1) clkGen2 = clkGen(clock=clk2, period=19) sayHello1 = sayHello(clock=clk1) sayHello2 = sayHello(to="MyHDL", clock=clk2) return clkGen1, clkGen2, sayHello1, sayHello2 \end{verbatim} As in standard Python, positional or named parameter association can be used in instantiations, or a mix of both\footnote{All positional parameters have to come before any named parameter.}. All these styles are demonstrated in the example above. As in hardware description languages, named association can be very useful if there are a lot of parameters, as the parameter order in the call does not matter in that case. \class{Simulation} constructor arguments can also be sequences of generators. In this way, they support hierarchy: the return value of a higher-level instantiating function can directly be used an argument. For example: \begin{verbatim} sim = Simulation(greetings()) sim.run(50) \end{verbatim} This produces the following output: \begin{verbatim} % python greetings.py 9 Hello MyHDL 10 Hello World! 28 Hello MyHDL 30 Hello World! 47 Hello MyHDL 50 Hello World! StopSimulation: Simulated for duration 50 \end{verbatim} \section{Bit-oriented operations} Hardware design involves dealing with bits and bit-oriented operations. The standard Python type \class{int} has most of the desired features, but lacks support for indexing and slicing. Therefore, \myhdl\ provides the \class{intbv} class. The name was chosen to suggest an integer with bit vector flavour. Class \class{intbv} works transparently as an integer and with other integer-like types. Like class \class{int}, it provides access to the underlying two's complement representation for bitwise operations. In addition, it is a mutable type that provides indexing and slicing operations, and some additional bit-oriented support such as concatenation. \subsection{Indexing operations} \label{gray} As an example, we will consider the design of a Gray encoder. The following code is a Gray encoder modeled in \myhdl{}: \begin{verbatim} def bin2gray(B, G, width): """ Gray encoder. B -- input intbv signal, binary encoded G -- output intbv signal, Gray encoded width -- bit width """ while 1: yield B for i in range(width): G.next[i] = B[i+1] ^ B[i] \end{verbatim} This code introduces a few new concepts. The string in triple quotes at the start of the function is a \dfn{doc string}. This is standard Python practice for structured documentation of code. Moreover, we use a third form of the \keyword{yield} statement: \samp{yield \var{signal}}. This specifies that the generator should resume whenever \var{signal} changes value. This is typically used to describe combinatorial logic. Finally, the code contains bit indexing operations and an exclusive-or operator as required for a Gray encoder. By convention, the lsb of an \class{intbv} object has index \code{0}. To verify the Gray encoder, we write a test bench that prints input and output for all possible input values: \begin{verbatim} def testBench(width): B = Signal(intbv(0)) G = Signal(intbv(0)) dut = bin2gray(B, G, width) def stimulus(): for i in range(2**width): B.next = intbv(i) yield delay(10) print "B: " + bin(B, width) + "| G: " + bin(G, width) return (dut, stimulus()) \end{verbatim} We use the conversion function \code{bin} to get a binary string representation of the signal values. This function is exported by the \code{myhdl} package and complements the standard Python \code{hex} and \code{oct} conversion functions. To demonstrate, we set up a simulation for a small width: \begin{verbatim} Simulation(testBench(width=3)).run() \end{verbatim} The simulation produces the following output: \begin{verbatim} % python bin2gray.py B: 000 | G: 000 B: 001 | G: 001 B: 010 | G: 011 B: 011 | G: 010 B: 100 | G: 110 B: 101 | G: 111 B: 110 | G: 101 B: 111 | G: 100 StopSimulation: No more events \end{verbatim} \subsection{Slicing operations} For a change, we will use a plain function as an example to illustrate slicing. The following function calculates the HEC byte of an ATM header. \begin{verbatim} from myhdl import intbv concat = intbv.concat # shorthand alias COSET = 0x55 def calculateHec(header): """ Return hec for an ATM header, represented as an intbv. The hec polynomial is 1 + x + x**2 + x**8. """ hec = intbv(0) for bit in header[32:]: hec[8:] = concat(hec[7:2], bit ^ hec[1] ^ hec[7], bit ^ hec[0] ^ hec[7], bit ^ hec[7] ) return hec ^ COSET \end{verbatim} The code shows how slicing access and assignment is supported on the \class{intbv} data type. In accordance with the most common hardware convention, and unlike standard Python, slicing ranges are downward. The code also demonstrates concatenation of \class{intbv} objects. 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 \emph{leftmost} item. The rightmost index is \code{0} by default, and can be ommitted from the slice. 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 \code{hex[8:]} has exactly \code{8} bits. Likewise, the slice \code{hex[7:2]} has \code{7-2=5} bits. You can think about it as follows: for a slice \code{[i:j]}, only bits below index \code{i} are included, and the bit with index \code{j} is the last bit included.