\chapter{Introduction to \myhdl\ \label{intro}} \section{A basic \myhdl\ simulation \label{intro-basic}} We will introduce \myhdl\ with a classic \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} All example code can be found in the distribution directory under \file{example/manual}. 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{The exception is the \samp{from module import *} syntax, that imports all the symbols from a module. Although this is generally considered bad practice, it can be tolerated for large modules that export a lot of symbols. One may argue that \code{myhdl} falls into that category.}. 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). When called, a generator function returns a \dfn{generator}, which is the basic simulation object in \myhdl{}. The \keyword{yield} statement in \myhdl{} has a similar meaning as the \keyword{wait} statement in VHDL: the statement suspends execution of a generator, and its clauses specify the conditions on which the generator should wait before resuming. In this case, it should \index{wait!for a delay}% wait for a delay. To make sure that a 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 \index{Verilog!always block}% Verilog \keyword{always} block \index{VHDL!process}% and a VHDL \keyword{process}. In the example, variable \code{gen} refers to a generator. To simulate it, 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 as a natural integer. \section{Concurrent generators and signals \label{intro-conc}} 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. With concurrency comes the problem of deterministic communication. Hardware languages use special objects to support deterministic communication between concurrent code. \myhdl\ has a \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 \index{VHDL!signal assignment}% the VHDL signal assignment and the \index{Verilog!non-blocking assignment}% Verilog non-blocking assignment. 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 the clock edge is achieved with a second form of the \keyword{yield} statement: \samp{yield posedge(\var{signal})}. At that point, the generator will \index{wait!for a rising edge}% wait for 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, instances and hierarchy \label{intro-hier}} 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. To make 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 as follows: \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 instantiation in hardware description languages and we will use the same terminology in \myhdl{}. A \myhdl\ \dfn{instance} is \index{instance!defined}% recursively defined as being either a sequence of instances, or a generator. Hierarchy can be modeled by defining the instances in a higher-level function, and returning them. A \class{Simulation} constructor takes an arbitrary number of instances as its arguments. 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 sim = Simulation(greetings()) sim.run(50) \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 go 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. The simulation 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} \begin{notice}[warning] Some commonly used terminology has different meanings in Python versus hardware design. Rather than artificially changing terminology, I think it's best to keep it and explicitly describing the differences. A \dfn{module} in Python refers to all source code in a particular file. A module can be reused by other modules by importing. In hardware design, \index{module!in Python versus hardware design}% a module is a reusable block of hardware with a well defined interface. It can be reused in another module by \dfn{instantiating} it. An \dfn{instance} in Python (and other object-oriented languages) refers to the object created by a \index{instance!in Python versus hardware design}% class constructor. In hardware design, an instance is a particular incarnation of a hardware module. Normally, the meaning should be clear from the context. Occasionally, I may qualify terms with the words 'hardware' or '\myhdl{}' to avoid ambiguity. \end{notice} \section{Bit oriented operations \label{intro-bit}} 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. For this reason, \myhdl\ provides the \class{intbv} class. The name was chosen to suggest an integer with bit vector flavor. 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{Bit indexing \label{intro-indexing}} \index{bit indexing} 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 """xc 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 \index{wait!for a signal value change}% wait for a signal value change. This is typically used to describe \index{combinatorial logic}% 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{Bit slicing \label{intro-slicing}} \index{bit slicing} 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. Both indices can be omitted from the slice. If the leftmost index is omitted, the meaning is to access ``all'' higher order bits. If the rightmost index is omitted, it is \code{0} by default. 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. \section{Bus-functional procedures \label{intro-bfm}} \index{bus-functional procedure}% A \dfn{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: \begin{verbatim} 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) \end{verbatim} 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: \begin{verbatim} testvals = (0xc5, 0x3a, 0x4b) def stimulus(): tx = Signal(1) for val in testvals: txData = intbv(val) yield rs232_tx(tx, txData) \end{verbatim} We use the bus-functional procedure call as a clause in a \code{yield} statement. This introduces a fourth form of the \code{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 \index{wait!for the completion of a generator}% wait for the completion of a generator. In this case, the original generator resumes when the \code{rs232_tx(tx, txData)} generator returns. When simulating this, we get: \begin{verbatim} -- 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 ... \end{verbatim} 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 \code{yield} statement. Until now, the \code{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 \index{sensitivity list}% 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: \begin{verbatim} 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 negedge(rx), 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) \end{verbatim} If the timeout condition is triggered, the receive bit \code{rx} will still be \code{1}. In that case, we raise an exception to stop the simulation. The \code{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 \code{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: \begin{verbatim} 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) \end{verbatim} 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: \begin{verbatim} -- 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 ... \end{verbatim} For completeness, we will verify the timeout behavior with a test bench that disconnects the \code{rx} from the \code{tx} signal, and we specify a small timeout for the receive procedure: \begin{verbatim} 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) \end{verbatim} The simulation now stops with a timeout exception after a few transmit cycles: \begin{verbatim} -- Transmitting 0xc5 -- TX: start bit TX: 1 TX: 0 TX: 1 StopSimulation: RX time out error \end{verbatim} 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 \emph{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: \begin{verbatim} 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) \end{verbatim} Simulating this shows how the transmission of the new byte starts before the previous one is received, potentially creating additional transmission errors: \begin{verbatim} -- 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 \end{verbatim} 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 \function{join} function. By joining clauses together in a \code{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: \begin{verbatim} 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)) \end{verbatim} Now, transmission of a new byte only starts when the previous one is received: \begin{verbatim} -- 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 \end{verbatim} \section{\myhdl\ and Python \label{intro-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 \code{myhdl}. Moreover, it is a design goal to keep the \code{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: \begin{itemize} \item Python is a very powerful high level language. This translates into high productivity and elegant solutions to complex problems. \item Python is continuously improved by some very clever minds, supported by a large and fast growing user base. Python profits fully from the open source development model. \item 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. \item Python has a powerful C extension model. All built-in types are written with the same C API that is available for custom extensions. To a module user, there is no difference between a standard Python module and a C extension module --- except performance. The typical Python development model is to prototype everything in Python until the application is stable, and (only) then rewrite performance critical modules in C if necessary. \end{itemize}