1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00
myhdl/doc/informal.tex
2003-02-05 21:59:42 +00:00

271 lines
8.6 KiB
TeX

\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 a Verilog \keyword{always} block or a
VHDL \keyword{process}.
In \myhdl\, the basic simulation objects are generators. Generators
are the returned from 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.
\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 list of
generators.
With concurrency comes the problem of deterministic
communication. Therefore, hardware languages use special objects to
support deterministic communication between concurrent
regions. \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 a
\keyword{yield} statement: \samp{yield posedge(\var{signal})}.
A \class{Simulation} 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
period is a parameter with a default value of \code{20}. This
\var{period} is an 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 talk():
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}
Like in standard Python, positional or named parameter association can
be used in instantiations, or a mix of the two \footnote{All
positional parameters have to come before any named parameter.}. All
these styles are demonstrated in the example above. Like in hardware
description languages, named association can be very useful if there
are a lot of parameters, as the parameter order 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(talk())
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 \class{int} has most of the desired
features, but lacks support for indexing and slicing. Therefore,
\myhdl\ provides a \class{intbv} class. It works
transparently as an integer and with integers, and like \class{int},
offers access to the underlying a 2'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.
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(width, B, G):
""" Gray encoder.
width -- bit width
B -- input intbv signal, binary encoded
G -- output intbv signal, gray encoded
"""
while 1:
yield B
for i in range(width):
G.next[i] = B.val[i+1] ^ B.val[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 to document function and other
code. Also, 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.
The actual code contains bit indexing operations and an exclusive-or
operator as required for a Gray encoder. Moreover, the code shows how
the actual value of a signal is accessed through the signal's
\var{val} attribute. In \myhdl{}, unlike traditional hardware
description languages, signals are explicitly modeled as composite
objects whose current and next values are accessed through attributes.