mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +08:00
partial checkin
This commit is contained in:
parent
4c78b0821c
commit
f1a73b4923
@ -17,13 +17,17 @@ see \url{http://www.python.org/doc/Newbies.html}.
|
||||
A working knowledge of a hardware description language such as Verilog
|
||||
or VHDL is helpful.
|
||||
|
||||
\section{A small tutorial on generators \label{tutorial}}
|
||||
\index{generators!tutorial on|(}
|
||||
Code examples in this manual are sometimes shortened for clarity.
|
||||
Complete executable examples can be found in the distribution directory at
|
||||
\file{example/manual/}.
|
||||
|
||||
Generators are a recent Python feature, introduced in
|
||||
Python~2.2. Therefore, there isn't a lot of tutorial material
|
||||
available yet. Because generators are the key concept in
|
||||
\myhdl{}, I include a small tutorial here.
|
||||
\section{A small tutorial on generators \label{tutorial}}
|
||||
\index{generators!tutorial on}
|
||||
|
||||
Generators are a relatively recent Python feature. They
|
||||
were introduced in Python~2.2.
|
||||
Because generators are the key concept in
|
||||
\myhdl{}, a small tutorial is included a here.
|
||||
|
||||
Consider the following nonsensical function:
|
||||
|
||||
@ -113,19 +117,49 @@ statements work as generalized
|
||||
\index{sensitivity list}%
|
||||
sensitivity lists.
|
||||
|
||||
If you want to know more about generators, consult the on-line Python
|
||||
For more info about generators, consult the on-line Python
|
||||
documentation, e.g. at \url{http://www.python.org/doc/2.2.2/whatsnew}.
|
||||
|
||||
|
||||
\section{About decorators \label{deco}}
|
||||
\index{decorators!about}
|
||||
|
||||
Python 2.4 introduced a new feature called decorators. MyHDL 0.5 defines
|
||||
a number of decorators to facilitate hardware descriptions, but many users may
|
||||
not be familiar with the concept. 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 \function{deco} is used in a decorator statement as follows:
|
||||
|
||||
\begin{verbatim}
|
||||
@deco
|
||||
def func(arg1, arg2, ...):
|
||||
<body>
|
||||
|
||||
This code is equivalent to the following template:
|
||||
|
||||
def func(arg1, arg2, ...):
|
||||
<body>
|
||||
func = deco(func)
|
||||
\end{verbatim}
|
||||
|
||||
Note that the decorator statement goes directly in front of the
|
||||
function declaration, and that the function name func is automatically
|
||||
reused.
|
||||
|
||||
MyHDL 0.5 uses decorators to create ready-to-simulate generators
|
||||
from local (embedded) function definitions. Their functionality
|
||||
and usage will be described extensively in this manual.
|
||||
|
||||
For more info about Python decorators, consult the on-line Python
|
||||
documentation, e.g. at \url{http://www.python.org/doc/2.4/whatsnew/node6.html}.
|
||||
|
||||
\begin{notice}[warning]
|
||||
As mentioned earlier, generators were introduced in Python~2.2. In
|
||||
that version, they were introduced as a ``future'' feature that has to
|
||||
be enabled explicitly. In Python~2.3, which is the latest stable
|
||||
Python version at the time of this writing, generators are enabled by
|
||||
default.
|
||||
|
||||
Besides generators, Python~2.3 has several other interesting new
|
||||
features, and it runs 25--35\% faster than Python~2.2. For these
|
||||
reasons, \myhdl\ requires Python~2.3.
|
||||
Because MyHDL 0.5 uses decorators, it requires Python 2.4 or a
|
||||
later version.
|
||||
\end{notice}
|
||||
\index{generators!tutorial on|)}
|
||||
|
||||
|
@ -3,177 +3,229 @@
|
||||
\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}:
|
||||
example. All example code can be found in the distribution directory
|
||||
under \file{example/manual}. Here are the contents of a \myhdl\
|
||||
simulation script called \file{hello1.py}:
|
||||
|
||||
\begin{verbatim}
|
||||
from myhdl import delay, now, Simulation
|
||||
from myhdl import Signal, delay, always, now, Simulation
|
||||
|
||||
def sayHello():
|
||||
while 1:
|
||||
yield delay(10)
|
||||
def HelloWorld():
|
||||
|
||||
@always(delay(10))
|
||||
def sayHello():
|
||||
print "%s Hello World!" % now()
|
||||
|
||||
gen = sayHello()
|
||||
sim = Simulation(gen)
|
||||
return sayHello
|
||||
|
||||
inst = HelloWorld()
|
||||
sim = Simulation(inst)
|
||||
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:
|
||||
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
|
||||
_SuspendSimulation: Simulated 30 timesteps
|
||||
\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
|
||||
\code{myhdl} package. In Python we can only use identifiers that are
|
||||
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{}.
|
||||
Then, we define a function called \function{HelloWorld}. In MyHDL,
|
||||
classic functions are used to model hardware modules. In particular,
|
||||
the parameter list is used to define the interface. In this first
|
||||
example, the interface is empty.
|
||||
|
||||
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.
|
||||
Inside the top level function we declared a local function called
|
||||
\function{sayHello} that defines the desired behavior. This function
|
||||
is decorated with an \function{@always} decorator that has a delay
|
||||
object as its parameter. The meaning is that the function will be
|
||||
executed whenever the specified delay has expired.
|
||||
|
||||
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}.
|
||||
Behind the curtains, the \function{@always} decorator creates a Python
|
||||
\emph{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.
|
||||
|
||||
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.
|
||||
Finally, the top level function returns the local generator. This code
|
||||
pattern is the simplest incarnation of the basic MyHDL code pattern
|
||||
to define the contents of a hardware module. We will describe the
|
||||
general case further on.
|
||||
|
||||
In MyHDL, we create an \emph{instance} of a hardware module by calling
|
||||
the corresponding function. In the example, variable \code{inst} refers
|
||||
to an instance of \function{HelloWorld}. To simulate the instance, we
|
||||
pass it as an argument to a \class{Simulation} object constructor. We
|
||||
then run the simulation for the desired amount of timesteps.
|
||||
|
||||
\section{Concurrent generators and signals \label{intro-conc}}
|
||||
\section{Signals, ports, and concurrency \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
|
||||
In the previous section, we simulated a design that consisted
|
||||
of a single generator. Of course,
|
||||
real hardware descriptions are not like that: 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\
|
||||
support deterministic communication between concurrent code.
|
||||
For this purpose \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:
|
||||
We will demonstrate the use of signals and the concept of concurrency
|
||||
by extending and modifying our first example. We define two hardware
|
||||
modules, one that drives a clock signal, and one that is sensitive
|
||||
to a positive edge on a clock signal:
|
||||
|
||||
|
||||
\begin{verbatim}
|
||||
clk = Signal(0)
|
||||
from myhdl import Signal, delay, always, now, Simulation
|
||||
|
||||
def clkGen():
|
||||
while 1:
|
||||
yield delay(10)
|
||||
clk.next = 1
|
||||
yield delay(10)
|
||||
clk.next = 0
|
||||
|
||||
def ClkDriver(clk):
|
||||
|
||||
@always(delay(10))
|
||||
def driveClk():
|
||||
clk.next = not clk
|
||||
|
||||
return driveClk
|
||||
|
||||
|
||||
def HelloWorld(clk):
|
||||
|
||||
@always(clk.posedge)
|
||||
def sayHello():
|
||||
print "%s Hello World!" % now()
|
||||
|
||||
return sayHello
|
||||
|
||||
|
||||
clk = Signal(0)
|
||||
clkdriver_inst = ClkDriver(clk)
|
||||
hello_inst = HelloWorld(clk)
|
||||
sim = Simulation(clkdriver_inst, hello_inst)
|
||||
sim.run(50)
|
||||
\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
|
||||
The clock driver function \function{ClkDriver} has a
|
||||
clock signal as its parameter. This is how a
|
||||
\emph{port} is modelled in MyHDL. The function
|
||||
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
|
||||
\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
|
||||
The \function{HelloWorld} function is modified from the
|
||||
first example. It now also takes a clock signal as parameter.
|
||||
Its generator is made sensitive to a rising
|
||||
\index{wait!for a rising edge}%
|
||||
wait for a rising edge on the signal.
|
||||
edge of the clock signal. This is specified by the
|
||||
\code{posedge} attribute of a signal. The edge
|
||||
specifier is the argument of the \code{@always}
|
||||
decorator. As a result, the decorated function
|
||||
will be executed on every rising clock edge.
|
||||
|
||||
The \class{Simulation} is now constructed with 2 generator arguments:
|
||||
The \code{clk} signal is constructed with an initial value
|
||||
\code{0}. When creating an instance of each to the two
|
||||
hardware modules, the same clock signal is passed as
|
||||
the argument. The result is that the two instances
|
||||
are now connected through the clock signal.
|
||||
The \class{Simulation} object is constructed with the
|
||||
two instances.
|
||||
|
||||
\begin{verbatim}
|
||||
sim = Simulation(clkGen(), sayHello())
|
||||
sim.run(50)
|
||||
\end{verbatim}
|
||||
|
||||
When we run this simulation, we get:
|
||||
When we run the simulation, we get:
|
||||
|
||||
\begin{verbatim}
|
||||
% python hello2.py
|
||||
10 Hello World!
|
||||
30 Hello World!
|
||||
50 Hello World!
|
||||
StopSimulation: Simulated for duration 50
|
||||
_SuspendSimulation: Simulated 50 timesteps
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\section{Parameters, instances and hierarchy \label{intro-hier}}
|
||||
\section{Parameters 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
|
||||
We have seen that MyHDL uses functions to model hardware
|
||||
modules. We have also seen that ports are modeled by using
|
||||
signals as parameters. To make designs reusable we will also
|
||||
want to use other objects as parameters. For example, we can
|
||||
change the clock generator function to make it more general
|
||||
and reusable, as follows:
|
||||
and reusable, by making the clock period parametrizable, as
|
||||
follows:
|
||||
|
||||
\begin{verbatim}
|
||||
def clkGen(clock, period=20):
|
||||
lowTime = int(period / 2)
|
||||
from myhdl import Signal, delay, instance, always, now, Simulation
|
||||
|
||||
def ClkDriver(clk, period=20):
|
||||
|
||||
lowTime = int(period/2)
|
||||
highTime = period - lowTime
|
||||
while 1:
|
||||
yield delay(lowTime)
|
||||
clock.next = 1
|
||||
yield delay(highTime)
|
||||
clock.next = 0
|
||||
|
||||
@instance
|
||||
def driveClk():
|
||||
while True:
|
||||
yield delay(lowTime)
|
||||
clk.next = 1
|
||||
yield delay(highTime)
|
||||
clk.next = 0
|
||||
|
||||
return driveClk
|
||||
\end{verbatim}
|
||||
|
||||
The clock signal is now a parameter of the function. Also, the clock
|
||||
In addition to the clock signal, 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:
|
||||
As the low time of the clock may differ from the high time in case of
|
||||
an odd period, we cannot use the \function{@always} decorator with a
|
||||
single delay value anymore. Instead, the \function{driveClk} function
|
||||
is now a generator function with an explicit definition of the desired
|
||||
behavior. You can see that \function{driveClk} is a generator function (as
|
||||
opposed to a classic function) because it contains \code{yield}
|
||||
statements.
|
||||
|
||||
When a generator function is called, it returns a generator object. In
|
||||
fact, this is mainly what the \function{@instance} decorator does. It
|
||||
is less sophisticated than the \function{@always} decorator,
|
||||
but it can be used to create a generator from any local generator
|
||||
function.
|
||||
|
||||
The \code{yield} statement is a general Python construct, but MyHDL
|
||||
uses it in a dedicated way. In MyHDL, 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.
|
||||
|
||||
Not that to make sure that the generator runs ``forever'', we wrap its
|
||||
behavior in a \code{while True} loop.
|
||||
|
||||
Likewise, we can define a general \function{Hello} function as follows:
|
||||
|
||||
\begin{verbatim}
|
||||
def sayHello(clock, to="World!"):
|
||||
while 1:
|
||||
yield posedge(clock)
|
||||
def Hello(clk, to="World!"):
|
||||
|
||||
@always(clk.posedge)
|
||||
def sayHello():
|
||||
print "%s Hello %s" % (now(), to)
|
||||
|
||||
return sayHello
|
||||
\end{verbatim}
|
||||
|
||||
We can create any number of generators by calling generator functions
|
||||
@ -190,15 +242,20 @@ 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
|
||||
|
||||
clkdriver_1 = ClkDriver(clk1) # positional and default association
|
||||
clkdriver_2 = ClkDriver(clk=clk2, period=19) # named assocation
|
||||
hello_1 = Hello(clk=clk1) # named and default association
|
||||
hello_2 = Hello(to="MyHDL", clk=clk2) # named assocation
|
||||
|
||||
sim = Simulation(greetings())
|
||||
return clkdriver_1, clkdriver_2, hello_1, hello_2
|
||||
|
||||
|
||||
inst = greetings()
|
||||
sim = Simulation(inst)
|
||||
sim.run(50)
|
||||
\end{verbatim}
|
||||
|
||||
@ -220,7 +277,7 @@ The simulation produces the following output:
|
||||
30 Hello World!
|
||||
47 Hello MyHDL
|
||||
50 Hello World!
|
||||
StopSimulation: Simulated for duration 50
|
||||
_SuspendSimulation: Simulated 50 timesteps
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
@ -273,30 +330,38 @@ As an example, we will consider the design of a Gray encoder. The
|
||||
following code is a Gray encoder modeled in \myhdl{}:
|
||||
|
||||
\begin{verbatim}
|
||||
from myhdl import Signal, delay, Simulation, always_comb, instance, intbv, bin
|
||||
|
||||
def bin2gray(B, G, width):
|
||||
""" Gray encoder.
|
||||
|
||||
B -- input intbv signal, binary encoded
|
||||
G -- output intbv signal, Gray encoded
|
||||
G -- output intbv signal, gray encoded
|
||||
width -- bit width
|
||||
|
||||
"""xc
|
||||
while 1:
|
||||
yield B
|
||||
"""
|
||||
|
||||
@always_comb
|
||||
def logic():
|
||||
for i in range(width):
|
||||
G.next[i] = B[i+1] ^ B[i]
|
||||
|
||||
return logic
|
||||
\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
|
||||
Python practice for structured documentation of code.
|
||||
|
||||
Furthermore, we introduce a third decorator: \function{@always_comb}.
|
||||
It is used with a classic function and specifies that the
|
||||
resulting generator should
|
||||
\index{wait!for a signal value change}%
|
||||
wait for a signal value change. This is typically used to
|
||||
wait for a value change on any input signal. This is typically used to
|
||||
describe
|
||||
\index{combinatorial logic}%
|
||||
combinatorial logic.
|
||||
combinatorial logic. The \function{@always_comb} decorator
|
||||
automatically infers which signals are used as inputs.
|
||||
|
||||
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}.
|
||||
@ -310,15 +375,16 @@ def testBench(width):
|
||||
B = Signal(intbv(0))
|
||||
G = Signal(intbv(0))
|
||||
|
||||
dut = bin2gray(B, G, width)
|
||||
dut = traceSignals(bin2gray, B, G, width)
|
||||
|
||||
@instance
|
||||
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())
|
||||
return dut, stimulus
|
||||
\end{verbatim}
|
||||
|
||||
We use the conversion function \code{bin} to get a binary
|
||||
@ -329,7 +395,8 @@ by the \code{myhdl} package and complements the standard Python
|
||||
To demonstrate, we set up a simulation for a small width:
|
||||
|
||||
\begin{verbatim}
|
||||
Simulation(testBench(width=3)).run()
|
||||
sim = Simulation(testBench(width=3))
|
||||
sim.run()
|
||||
\end{verbatim}
|
||||
|
||||
The simulation produces the following output:
|
||||
@ -355,8 +422,7 @@ slicing. The following function calculates the HEC byte of an ATM
|
||||
header.
|
||||
|
||||
\begin{verbatim}
|
||||
from myhdl import intbv
|
||||
concat = intbv.concat # shorthand alias
|
||||
from myhdl import intbv, concat
|
||||
|
||||
COSET = 0x55
|
||||
|
||||
@ -395,6 +461,9 @@ to avoid one-off count issues in practice. For example, the slice
|
||||
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.
|
||||
|
||||
When an intbv object is sliced, a new intbv object is returned. This
|
||||
new intbv always has a positive value, even when the original object
|
||||
was negative.
|
||||
|
||||
\section{Bus-functional procedures \label{intro-bfm}}
|
||||
|
||||
|
@ -192,7 +192,7 @@ are forked, while the original generator resumes immediately.
|
||||
MyHDL defines a number of decorator functions, that make it easier to
|
||||
create generators from local generator function.
|
||||
|
||||
\begin{funcdesc}{instance}{}
|
||||
\begin{funcdesc}{@instance}{}
|
||||
The \code{@instance} decorator is the most general decorator. It
|
||||
automatically creates a generator by calling the generator function,
|
||||
and by reusing its name.
|
||||
@ -214,10 +214,10 @@ This is equivalent to:
|
||||
\begin{verbatim}
|
||||
def top(...):
|
||||
...
|
||||
def gen_func():
|
||||
def _gen_func():
|
||||
<generator body>
|
||||
...
|
||||
inst = gen_func()
|
||||
inst = _gen_func()
|
||||
...
|
||||
return inst, ...
|
||||
\end{verbatim}
|
||||
@ -225,10 +225,10 @@ def top(...):
|
||||
\end{funcdesc}
|
||||
|
||||
|
||||
\begin{funcdesc}{always}{arg \optional{, *args}}
|
||||
\begin{funcdesc}{@always}{arg \optional{, *args}}
|
||||
|
||||
The \code{@always} decorator is a specialized decorator for a widely used
|
||||
pattern. It is used as follows:
|
||||
The \code{@always} decorator is a specialized decorator that targets a widely used
|
||||
coding pattern. It is used as follows:
|
||||
|
||||
\begin{verbatim}
|
||||
def top(...):
|
||||
@ -242,16 +242,18 @@ def top(...):
|
||||
|
||||
This is equivalent to the following:
|
||||
|
||||
|
||||
\begin{verbatim}
|
||||
def top(...):
|
||||
...
|
||||
def gen_func()
|
||||
def _func():
|
||||
<body>
|
||||
|
||||
def _gen_func()
|
||||
while True:
|
||||
yield event1, event2, ...
|
||||
<body>
|
||||
_func()
|
||||
...
|
||||
inst = gen_func()
|
||||
inst = _gen_func()
|
||||
...
|
||||
return inst, ...
|
||||
\end{verbatim}
|
||||
@ -259,12 +261,13 @@ def top(...):
|
||||
|
||||
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.
|
||||
|
||||
|
||||
\end{funcdesc}
|
||||
|
||||
|
||||
\begin{funcdesc}{always_comb}{}
|
||||
\begin{funcdesc}{@always_comb}{}
|
||||
|
||||
|
||||
The \code{@always_comb} decorator is used to describe combinatorial
|
||||
|
Loading…
x
Reference in New Issue
Block a user