1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00

partial checkin

This commit is contained in:
jand 2005-12-10 23:06:55 +00:00
parent fc137e5049
commit eee364fd65
3 changed files with 81 additions and 81 deletions

View File

@ -26,7 +26,7 @@ DOCFILES= $(HOWTOSTYLES) \
MANUALFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
manual/MyHDL.tex \
manual/background.tex \
manual/informal.tex \
manual/intro.tex \
manual/modeling.tex \
manual/unittest.tex \
manual/cosimulation.tex \

View File

@ -376,7 +376,7 @@ def testBench(width):
B = Signal(intbv(0))
G = Signal(intbv(0))
dut = traceSignals(bin2gray, B, G, width)
dut = bin2gray(B, G, width)
@instance
def stimulus():

View File

@ -95,11 +95,9 @@ def top(..., n=8):
\subsection{Inferring the list of instances \label{model-infer-instlist}}
In \myhdl{}, instances have to be returned explicitly by
a top level function. This procedural approach has important
advantages, as shown earlier. However, if we just want to
return all defined instances, it may be convenient to assemble
a top level function. It may be convenient to assemble
the list of instances automatically. For this purpose,
\myhdl{}~0.3 provides the function \function{instances()}.
\myhdl provides the function \function{instances()}.
Using the first example in this section, it is used as follows:
\begin{verbatim}
@ -131,40 +129,28 @@ as is typically used for synthesizable models in Verilog or VHDL.
\subsubsection{Template \label{model-comb-templ}}
Combinatorial logic is described with a generator function code template as
Combinatorial logic is described with a code pattern as
follows:
\begin{verbatim}
def combinatorialLogic(<arguments>)
while 1:
yield <input signals>
def top(<parameters>)
...
@always_comb
def combLogic():
<functional code>
...
return combLogic, ...
\end{verbatim}
The overall code is wrapped in a \code{while 1} statement to keep the
generator alive. All input signals are clauses in the \code{yield}
statement, so that the generator resumes whenever one of the inputs
changes.
Note that the input signals are listed explicitly in the
template. Alternatively, \myhdl\ provides the \function{always_comb()}
function to infer the input signals automatically.
\footnote{The name \function{always_comb()} refers to
a construct with similar semantics in SystemVerilog.}.
The argument of
\function{always_comb()} is a local function that specifies
what happens when one of the input signals
changes. It returns a generator that is
sensitive to all inputs, and that will run the function argument
whenever an input changes. Using \function{always_comb}, the template
can be rewritten as follows:
\begin{verbatim}
def combinatorialLogic(<arguments>)
def logicFunction():
<functional code>
return always_comb(logicFunction)
\end{verbatim}
The \function{@always_comb} decorator is used to describe
combinatorial logic.
\footnote{The name \function{always_comb} refers to a construct with
similar semantics in SystemVerilog.}.
The decorated function is a local function that specifies what
happens when one of the input signals of the logic changes. The
\function{@always_comb} decorator infers the input signals
automatically. It returns a generator that is sensitive to all inputs,
and that will run the function whenever an input changes.
\subsubsection{Example \label{model-comb-ex}}
@ -172,7 +158,10 @@ def combinatorialLogic(<arguments>)
The following is an example of a combinatorial multiplexer:
\begin{verbatim}
def mux(z, a, b, sel):
from myhdl import Signal, Simulation, delay, always_comb
def Mux(z, a, b, sel):
""" Multiplexer.
z -- mux output
@ -180,30 +169,19 @@ def mux(z, a, b, sel):
sel -- control input: select a if asserted, otherwise b
"""
while 1:
yield a, b, sel
if sel == 1:
z.next = a
else:
z.next = b
\end{verbatim}
Alternatively, it could be written as follows, using
\function{always_comb()}:
\begin{verbatim}
def mux(z, a, b, sel):
def muxlogic():
@always_comb
def muxLogic():
if sel == 1:
z.next = a
else:
z.next = b
return always_comb(muxlogic)
return muxLogic
\end{verbatim}
To verify, let's simulate this logic with some random patterns. The
To verify it, we will simulate the logic with some random patterns. The
\code{random} module in Python's standard library comes in handy for
such purposes. The function \code{randrange(\var{n})} returns a random
natural integer smaller than \var{n}. It is used in the test bench
@ -212,9 +190,9 @@ code to produce random input values:
\begin{verbatim}
from random import randrange
(z, a, b, sel) = [Signal(0) for i in range(4)]
z, a, b, sel = [Signal(0) for i in range(4)]
MUX_1 = mux(z, a, b, sel)
mux_1 = Mux(z, a, b, sel)
def test():
print "z a b sel"
@ -222,8 +200,11 @@ def test():
a.next, b.next, sel.next = randrange(8), randrange(8), randrange(2)
yield delay(10)
print "%s %s %s %s" % (z, a, b, sel)
Simulation(MUX_1, test()).run()
test_1 = test()
sim = Simulation(mux_1, test_1)
sim.run()
\end{verbatim}
Because of the randomness, the simulation output varies between runs
@ -257,13 +238,16 @@ common patterns: a template with a rising clock edge and an
asynchronous reset signal. Other templates are similar.
\begin{verbatim}
def sequentialLogic(<arguments>, clock, ..., reset, ...)
while 1:
yield posedge(clock), negedge(reset)
def top(<parameters>, clock, ..., reset, ...)
...
@always(clock.posedge, reset.negedge)
def seqLogic():
if reset == <active level>:
<reset code>
else:
<functional code>
...
return seqLogic, ...
\end{verbatim}
@ -272,9 +256,13 @@ The following code is a description of an incrementer with enable, and
an asynchronous power-up reset.
\begin{verbatim}
from random import randrange
from myhdl import *
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
def Inc(count, enable, clock, reset, n):
""" Incrementer with enable.
count -- output
@ -284,13 +272,16 @@ def Inc(count, enable, clock, reset, n):
n -- counter max value
"""
while 1:
yield posedge(clock), negedge(reset)
@always(clock.posedge, reset.negedge)
def incLogic():
if reset == ACTIVE_LOW:
count.next = 0
else:
if enable:
count.next = (count + 1) % n
return incLogic
\end{verbatim}
For the test bench, we will use an independent clock generator, stimulus
@ -300,33 +291,42 @@ simulation run. The test bench for a small incrementer and a small
number of patterns is a follows:
\begin{verbatim}
count, enable, clock, reset = [Signal(intbv(0)) for i in range(4)]
def testbench():
count, enable, clock, reset = [Signal(intbv(0)) for i in range(4)]
INC_1 = Inc(count, enable, clock, reset, n=4)
inc_1 = Inc(count, enable, clock, reset, n=4)
def clockGen():
while 1:
yield delay(10)
HALF_PERIOD = delay(10)
@always(HALF_PERIOD)
def clockGen():
clock.next = not clock
def stimulus():
reset.next = ACTIVE_LOW
yield negedge(clock)
reset.next = INACTIVE_HIGH
for i in range(12):
enable.next = min(1, randrange(3))
@instance
def stimulus():
reset.next = ACTIVE_LOW
yield negedge(clock)
raise StopSimulation
reset.next = INACTIVE_HIGH
for i in range(12):
enable.next = min(1, randrange(3))
yield negedge(clock)
raise StopSimulation
def monitor():
print "enable count"
yield posedge(reset)
while 1:
yield posedge(clock)
yield delay(1)
print " %s %s" % (enable, count)
Simulation(clockGen(), stimulus(), monitor(), INC_1).run()
@instance
def monitor():
print "enable count"
yield posedge(reset)
while 1:
yield posedge(clock)
yield delay(1)
print " %s %s" % (enable, count)
return clockGen, stimulus, inc_1, monitor
tb = testbench()
def main():
Simulation(tb).run()
\end{verbatim}
The simulation produces the following output: