From eee364fd6542acec442c29768039a27c6fc291e8 Mon Sep 17 00:00:00 2001 From: jand Date: Sat, 10 Dec 2005 23:06:55 +0000 Subject: [PATCH] partial checkin --- doc/Makefile.deps | 2 +- doc/manual/intro.tex | 2 +- doc/manual/modeling.tex | 158 ++++++++++++++++++++-------------------- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/doc/Makefile.deps b/doc/Makefile.deps index 9d6fade5..b690a653 100644 --- a/doc/Makefile.deps +++ b/doc/Makefile.deps @@ -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 \ diff --git a/doc/manual/intro.tex b/doc/manual/intro.tex index d3d8eca1..236e0e09 100644 --- a/doc/manual/intro.tex +++ b/doc/manual/intro.tex @@ -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(): diff --git a/doc/manual/modeling.tex b/doc/manual/modeling.tex index a061ff83..7fcaaf8e 100644 --- a/doc/manual/modeling.tex +++ b/doc/manual/modeling.tex @@ -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() - while 1: - yield +def top() + ... + @always_comb + def combLogic(): + ... + 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() - def logicFunction(): - - 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() 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(, clock, ..., reset, ...) - while 1: - yield posedge(clock), negedge(reset) +def top(, clock, ..., reset, ...) + ... + @always(clock.posedge, reset.negedge) + def seqLogic(): if reset == : else: + ... + 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: