mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +08:00
Use myhdldoctools instead of doctest
This commit is contained in:
parent
3b5ad3b471
commit
f272f8fba4
@ -31,27 +31,26 @@ Combinatorial logic
|
||||
Template
|
||||
--------
|
||||
|
||||
.. testsetup:: *
|
||||
|
||||
from myhdl import *
|
||||
|
||||
|
||||
Combinatorial logic is described with a code pattern as follows::
|
||||
|
||||
from myhdl import block, always_comb
|
||||
|
||||
@block
|
||||
def top(<parameters>):
|
||||
...
|
||||
@always_comb
|
||||
def combLogic():
|
||||
def comb_logic():
|
||||
<functional code>
|
||||
...
|
||||
return combLogic, ...
|
||||
|
||||
The :func:`always_comb` decorator describes combinatorial logic. [#]_. The
|
||||
decorated function is a local function that specifies what happens when one of
|
||||
the input signals of the logic changes. The :func:`always_comb` decorator
|
||||
infers the input signals automatically. It returns a generator that is sensitive
|
||||
to all inputs, and that executes the function whenever an input changes.
|
||||
return comb_logic, ...
|
||||
|
||||
The :func:`always_comb` decorator describes combinatorial logic. The name refers
|
||||
to a similar construct in SystemVerilog. The decorated function is a local
|
||||
function that specifies what happens when one of the input signals of the logic
|
||||
changes. The :func:`always_comb` decorator infers the input signals
|
||||
automatically. It returns a generator that is sensitive to all inputs, and that
|
||||
executes the function whenever an input changes.
|
||||
|
||||
.. _model-comb-ex:
|
||||
|
||||
@ -60,76 +59,21 @@ Example
|
||||
|
||||
The following is an example of a combinatorial multiplexer
|
||||
|
||||
.. include-example:: mux.py
|
||||
|
||||
.. testcode:: comb1
|
||||
|
||||
from myhdl import Signal, Simulation, delay, always_comb
|
||||
|
||||
def Mux(z, a, b, sel):
|
||||
""" Multiplexer.
|
||||
|
||||
z -- mux output
|
||||
a, b -- data inputs
|
||||
sel -- control input: select a if asserted, otherwise b
|
||||
|
||||
"""
|
||||
|
||||
@always_comb
|
||||
def muxLogic():
|
||||
if sel == 1:
|
||||
z.next = a
|
||||
else:
|
||||
z.next = b
|
||||
|
||||
return muxLogic
|
||||
|
||||
# Once we've created some signals...
|
||||
z, a, b, sel = [Signal(intbv(0)) for i in range(4)]
|
||||
|
||||
# ...it can be instantiated as follows
|
||||
mux_1 = Mux(z, a, b, sel)
|
||||
|
||||
To verify it, we will simulate the logic with some random patterns. The
|
||||
``random`` module in Python's standard library comes in handy for such purposes.
|
||||
The function ``randrange(n)`` returns a random natural integer smaller than *n*.
|
||||
It is used in the test bench code to produce random input values
|
||||
It is used in the test bench code to produce random input values.
|
||||
|
||||
.. testcode:: comb1
|
||||
:hide:
|
||||
.. include-example:: test_mux.py
|
||||
|
||||
import random
|
||||
random.seed(0xDECAFBAD)
|
||||
It is often useful to keep the random values reproducible. This can be
|
||||
accomplished by providing a seed value as in the code. The run produces the
|
||||
following output:
|
||||
|
||||
.. testcode:: comb1
|
||||
|
||||
from random import randrange
|
||||
|
||||
def test():
|
||||
|
||||
print "z a b sel"
|
||||
for i in range(8):
|
||||
a.next, b.next, sel.next = randrange(8), randrange(8), randrange(2)
|
||||
yield delay(10)
|
||||
print "%s %s %s %s" % (z, a, b, sel)
|
||||
|
||||
|
||||
test_1 = test()
|
||||
sim = Simulation(mux_1, test_1).run()
|
||||
|
||||
Because of the randomness, the simulation output varies between runs [#]_. One
|
||||
particular run produced the following output
|
||||
|
||||
.. testoutput:: comb1
|
||||
|
||||
z a b sel
|
||||
6 6 0 1
|
||||
7 7 2 1
|
||||
7 6 7 0
|
||||
0 3 0 0
|
||||
1 1 1 1
|
||||
1 5 1 0
|
||||
2 3 2 0
|
||||
1 1 0 1
|
||||
.. run-example:: test_mux.py
|
||||
|
||||
.. _model-seq:
|
||||
|
||||
@ -138,7 +82,6 @@ Sequential logic
|
||||
|
||||
.. index:: single: sequential logic
|
||||
|
||||
|
||||
.. _model-seq-templ:
|
||||
|
||||
Template
|
||||
@ -148,13 +91,16 @@ Sequential RTL models are sensitive to a clock edge. In addition, they may be
|
||||
sensitive to a reset signal. The :func:`always_seq` decorator supports this
|
||||
model directly::
|
||||
|
||||
from myhdl import block, always_seq
|
||||
|
||||
@instance
|
||||
def top(<parameters>, clock, ..., reset, ...):
|
||||
...
|
||||
@always_seq(clock.posedge, reset=reset)
|
||||
def seqLogic():
|
||||
def seq_logic():
|
||||
<functional code>
|
||||
...
|
||||
return seqLogic, ...
|
||||
return seq_logic, ...
|
||||
|
||||
The :func:`always_seq` decorator automatically infers the reset
|
||||
functionality. It detects which signals need to be reset, and uses their
|
||||
@ -175,33 +121,9 @@ Example
|
||||
-------
|
||||
|
||||
The following code is a description of an incrementer with enable, and an
|
||||
asynchronous reset.
|
||||
|
||||
.. testcode:: seq1
|
||||
|
||||
from myhdl import *
|
||||
|
||||
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
|
||||
|
||||
def Inc(count, enable, clock, reset, n):
|
||||
|
||||
""" Incrementer with enable.
|
||||
|
||||
count -- output
|
||||
enable -- control input, increment when 1
|
||||
clock -- clock input
|
||||
reset -- asynchronous reset input
|
||||
n -- counter max value
|
||||
|
||||
"""
|
||||
|
||||
@always_seq(clock.posedge, reset=reset)
|
||||
def incLogic():
|
||||
if enable:
|
||||
count.next = (count + 1) % n
|
||||
|
||||
return incLogic
|
||||
asynchronous reset.
|
||||
|
||||
.. include-example:: inc.py
|
||||
|
||||
|
||||
For the test bench, we will use an independent clock generator, stimulus
|
||||
@ -209,70 +131,11 @@ generator, and monitor. After applying enough stimulus patterns, we can raise
|
||||
the :func:`StopSimulation()` exception to stop the simulation run. The test bench for
|
||||
a small incrementer and a small number of patterns is a follows
|
||||
|
||||
.. testcode:: seq1
|
||||
:hide:
|
||||
|
||||
import random
|
||||
random.seed(0xDECAFBAD)
|
||||
|
||||
.. testcode:: seq1
|
||||
|
||||
from random import randrange
|
||||
|
||||
def testbench():
|
||||
count, enable, clock = [Signal(intbv(0)) for i in range(3)]
|
||||
reset = ResetSignal(0, active=ACTIVE_LOW, async=True)
|
||||
|
||||
inc_1 = Inc(count, enable, clock, reset, n=4)
|
||||
|
||||
HALF_PERIOD = delay(10)
|
||||
|
||||
@always(HALF_PERIOD)
|
||||
def clockGen():
|
||||
clock.next = not clock
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
reset.next = ACTIVE_LOW
|
||||
yield clock.negedge
|
||||
reset.next = INACTIVE_HIGH
|
||||
for i in range(12):
|
||||
enable.next = min(1, randrange(3))
|
||||
yield clock.negedge
|
||||
raise StopSimulation
|
||||
|
||||
@instance
|
||||
def monitor():
|
||||
print "enable count"
|
||||
yield reset.posedge
|
||||
while 1:
|
||||
yield clock.posedge
|
||||
yield delay(1)
|
||||
print " %s %s" % (enable, count)
|
||||
|
||||
return clockGen, stimulus, inc_1, monitor
|
||||
|
||||
|
||||
tb = testbench()
|
||||
Simulation(tb).run()
|
||||
.. include-example:: test_inc.py
|
||||
|
||||
The simulation produces the following output
|
||||
|
||||
.. testoutput:: seq1
|
||||
|
||||
enable count
|
||||
1 1
|
||||
0 1
|
||||
1 2
|
||||
1 3
|
||||
0 3
|
||||
1 0
|
||||
1 1
|
||||
1 2
|
||||
1 3
|
||||
1 0
|
||||
0 0
|
||||
1 1
|
||||
.. run-example:: test_inc.py
|
||||
|
||||
.. _mode-seq-templ-alt:
|
||||
|
||||
@ -283,15 +146,20 @@ The template with the :func:`always_seq` decorator is convenient
|
||||
as it infers the reset functionality automatically. Alternatively,
|
||||
you can use a more explicit template as follows::
|
||||
|
||||
from myhdl import block, always
|
||||
|
||||
@block
|
||||
def top(<parameters>, clock, ..., reset, ...):
|
||||
...
|
||||
@always(clock.posedge, reset.negedge)
|
||||
def seqLogic():
|
||||
def seq_logic():
|
||||
if not reset:
|
||||
<reset code>
|
||||
else:
|
||||
<functional code>
|
||||
|
||||
return seq_logic,...
|
||||
|
||||
With this template, the reset values have to be specified
|
||||
explicitly.
|
||||
|
||||
@ -353,55 +221,7 @@ When the ``syncFlag`` is confirmed on the expected position, the FSM declares
|
||||
``SYNC``, otherwise it falls back to the ``SEARCH`` state. This FSM can be
|
||||
coded as follows
|
||||
|
||||
.. testcode:: sm1
|
||||
|
||||
from myhdl import *
|
||||
|
||||
ACTIVE_LOW = 0
|
||||
FRAME_SIZE = 8
|
||||
t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
|
||||
|
||||
def FramerCtrl(SOF, state, syncFlag, clk, reset):
|
||||
|
||||
""" Framing control FSM.
|
||||
|
||||
SOF -- start-of-frame output bit
|
||||
state -- FramerState output
|
||||
syncFlag -- sync pattern found indication input
|
||||
clk -- clock input
|
||||
reset_n -- active low reset
|
||||
|
||||
"""
|
||||
|
||||
index = Signal(0) # position in frame
|
||||
|
||||
@always_seq(clk.posedge, reset=reset)
|
||||
def FSM():
|
||||
index.next = (index + 1) % FRAME_SIZE
|
||||
SOF.next = 0
|
||||
|
||||
if state == t_State.SEARCH:
|
||||
index.next = 1
|
||||
if syncFlag:
|
||||
state.next = t_State.CONFIRM
|
||||
|
||||
elif state == t_State.CONFIRM:
|
||||
if index == 0:
|
||||
if syncFlag:
|
||||
state.next = t_State.SYNC
|
||||
else:
|
||||
state.next = t_State.SEARCH
|
||||
|
||||
elif state == t_State.SYNC:
|
||||
if index == 0:
|
||||
if not syncFlag:
|
||||
state.next = t_State.SEARCH
|
||||
SOF.next = (index == FRAME_SIZE-1)
|
||||
|
||||
else:
|
||||
raise ValueError("Undefined state")
|
||||
|
||||
return FSM
|
||||
.. include-example:: fsm.py
|
||||
|
||||
.. index:: single: waveform viewing
|
||||
|
||||
@ -410,7 +230,7 @@ waveform viewing. During simulation, signal changes can be written to a VCD
|
||||
output file. The VCD file can then be loaded and viewed in a waveform viewer
|
||||
tool such as :program:`gtkwave`.
|
||||
|
||||
.. %
|
||||
.. %
|
||||
|
||||
The user interface of this feature consists of a single function,
|
||||
:func:`traceSignals`. To explain how it works, recall that in MyHDL, an
|
||||
@ -433,87 +253,8 @@ call.
|
||||
A small test bench for our framing controller example, with signal tracing
|
||||
enabled, is shown below:
|
||||
|
||||
.. testcode:: sm1
|
||||
.. include-example:: test_fsm.py
|
||||
|
||||
def testbench():
|
||||
|
||||
SOF = Signal(bool(0))
|
||||
syncFlag = Signal(bool(0))
|
||||
clk = Signal(bool(0))
|
||||
reset = ResetSignal(1, active=ACTIVE_LOW, async=True)
|
||||
state = Signal(t_State.SEARCH)
|
||||
|
||||
framectrl = FramerCtrl(SOF, state, syncFlag, clk, reset)
|
||||
|
||||
@always(delay(10))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
for i in range(3):
|
||||
yield clk.posedge
|
||||
for n in (12, 8, 8, 4):
|
||||
syncFlag.next = 1
|
||||
yield clk.posedge
|
||||
syncFlag.next = 0
|
||||
for i in range(n-1):
|
||||
yield clk.posedge
|
||||
raise StopSimulation
|
||||
|
||||
@always_seq(clk.posedge, reset=reset)
|
||||
def output_printer():
|
||||
print syncFlag, SOF, state
|
||||
|
||||
return framectrl, clkgen, stimulus, output_printer
|
||||
|
||||
tb_fsm = traceSignals(testbench)
|
||||
sim = Simulation(tb_fsm)
|
||||
sim.run()
|
||||
|
||||
.. testoutput:: sm1
|
||||
:hide:
|
||||
|
||||
False False SEARCH
|
||||
False False SEARCH
|
||||
False False SEARCH
|
||||
1 False SEARCH
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False SEARCH
|
||||
0 False SEARCH
|
||||
0 False SEARCH
|
||||
1 False SEARCH
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
0 False CONFIRM
|
||||
1 False CONFIRM
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
1 True SYNC
|
||||
0 False SYNC
|
||||
0 False SYNC
|
||||
|
||||
.. testcleanup:: sm1
|
||||
|
||||
import os
|
||||
os.remove('testbench.vcd')
|
||||
|
||||
When we run the test bench, it generates a VCD file called
|
||||
:file:`testbench.vcd`. When we load this file into :program:`gtkwave`, we can
|
||||
view the waveforms:
|
||||
@ -533,14 +274,3 @@ string representation, as returned by the standard :func:`str` function.
|
||||
Support for literal string representations is not part of the VCD standard. It
|
||||
is specific to :program:`gtkwave`. To generate a standard VCD file, you need to
|
||||
use signals with a defined bit width only.
|
||||
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#] The name :func:`always_comb` refers to a construct with similar semantics in
|
||||
SystemVerilog.
|
||||
|
||||
.. [#] It also possible to have a reproducible random output, by explicitly providing a
|
||||
seed value. See the documentation of the ``random`` module.
|
||||
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 14 KiB |
@ -22,7 +22,7 @@ class RunExample(Directive):
|
||||
env = document.settings.env
|
||||
_ , wd = env.relfn2path(example_dir)
|
||||
prog = self.arguments[0]
|
||||
out = subprocess.check_output(['python', '-u', prog], cwd=wd,
|
||||
out = subprocess.check_output(['python3', '-u', prog], cwd=wd,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
out = '$ python {}\n{}'.format(prog, out)
|
||||
|
@ -6,6 +6,6 @@ def Hello(clk, to="World!"):
|
||||
|
||||
@always(clk.posedge)
|
||||
def say_hello():
|
||||
print "%s Hello %s" % (now(), to)
|
||||
print("%s Hello %s" % (now(), to))
|
||||
|
||||
return say_hello
|
||||
|
17
example/manual/conv_inc.py
Normal file
17
example/manual/conv_inc.py
Normal file
@ -0,0 +1,17 @@
|
||||
from myhdl import toVerilog, toVHDL, Signal, ResetSignal, modbv
|
||||
from inc import inc
|
||||
|
||||
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
|
||||
|
||||
|
||||
# conversion
|
||||
m = 8
|
||||
|
||||
count = Signal(modbv(0)[m:])
|
||||
enable = Signal(bool(0))
|
||||
clock = Signal(bool(0))
|
||||
reset = ResetSignal(0, active=0, async=True)
|
||||
|
||||
inc_inst = inc(count, enable, clock, reset)
|
||||
inc_inst = toVerilog(inc, count, enable, clock, reset)
|
||||
inc_inst = toVHDL(inc, count, enable, clock, reset)
|
@ -1,95 +1,54 @@
|
||||
import myhdl
|
||||
from myhdl import *
|
||||
from myhdl import block, always_seq, Signal, intbv, enum
|
||||
|
||||
ACTIVE_LOW = 0
|
||||
FRAME_SIZE = 8
|
||||
t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
|
||||
t_state = enum('SEARCH', 'CONFIRM', 'SYNC')
|
||||
|
||||
@block
|
||||
def FramerCtrl(SOF, state, syncFlag, clk, reset_n):
|
||||
|
||||
def framer_ctrl(sof, state, sync_flag, clk, reset_n):
|
||||
|
||||
""" Framing control FSM.
|
||||
|
||||
SOF -- start-of-frame output bit
|
||||
sof -- start-of-frame output bit
|
||||
state -- FramerState output
|
||||
syncFlag -- sync pattern found indication input
|
||||
sync_flag -- sync pattern found indication input
|
||||
clk -- clock input
|
||||
reset_n -- active low reset
|
||||
|
||||
"""
|
||||
|
||||
index = Signal(0) # position in frame
|
||||
|
||||
@always(clk.posedge, reset_n.negedge)
|
||||
"""
|
||||
|
||||
index = Signal(intbv(0, min=0, max=FRAME_SIZE)) # position in frame
|
||||
|
||||
@always_seq(clk.posedge, reset=reset_n)
|
||||
def FSM():
|
||||
if reset_n == ACTIVE_LOW:
|
||||
SOF.next = 0
|
||||
sof.next = 0
|
||||
index.next = 0
|
||||
state.next = t_State.SEARCH
|
||||
state.next = t_state.SEARCH
|
||||
|
||||
else:
|
||||
index.next = (index + 1) % FRAME_SIZE
|
||||
SOF.next = 0
|
||||
sof.next = 0
|
||||
|
||||
if state == t_State.SEARCH:
|
||||
if state == t_state.SEARCH:
|
||||
index.next = 1
|
||||
if syncFlag:
|
||||
state.next = t_State.CONFIRM
|
||||
if sync_flag:
|
||||
state.next = t_state.CONFIRM
|
||||
|
||||
elif state == t_State.CONFIRM:
|
||||
elif state == t_state.CONFIRM:
|
||||
if index == 0:
|
||||
if syncFlag:
|
||||
state.next = t_State.SYNC
|
||||
if sync_flag:
|
||||
state.next = t_state.SYNC
|
||||
else:
|
||||
state.next = t_State.SEARCH
|
||||
state.next = t_state.SEARCH
|
||||
|
||||
elif state == t_State.SYNC:
|
||||
elif state == t_state.SYNC:
|
||||
if index == 0:
|
||||
if not syncFlag:
|
||||
state.next = t_State.SEARCH
|
||||
SOF.next = (index == FRAME_SIZE-1)
|
||||
if not sync_flag:
|
||||
state.next = t_state.SEARCH
|
||||
sof.next = (index == FRAME_SIZE-1)
|
||||
|
||||
else:
|
||||
raise ValueError("Undefined state")
|
||||
|
||||
return FSM
|
||||
|
||||
|
||||
@block
|
||||
def testbench():
|
||||
|
||||
SOF = Signal(bool(0))
|
||||
syncFlag = Signal(bool(0))
|
||||
clk = Signal(bool(0))
|
||||
reset_n = Signal(bool(1))
|
||||
state = Signal(t_State.SEARCH)
|
||||
|
||||
framectrl = FramerCtrl(SOF, state, syncFlag, clk, reset_n)
|
||||
|
||||
@always(delay(10))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
for i in range(3):
|
||||
yield clk.posedge
|
||||
for n in (12, 8, 8, 4):
|
||||
syncFlag.next = 1
|
||||
yield clk.posedge
|
||||
syncFlag.next = 0
|
||||
for i in range(n-1):
|
||||
yield clk.posedge
|
||||
raise StopSimulation
|
||||
|
||||
return framectrl, clkgen, stimulus
|
||||
|
||||
|
||||
def main():
|
||||
tb = testbench()
|
||||
tb.config_sim(trace=True)
|
||||
tb.run_sim()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -11,7 +11,7 @@ def HelloWorld():
|
||||
|
||||
@always(clk.posedge)
|
||||
def say_hello():
|
||||
print "%s Hello World!" % now()
|
||||
print("%s Hello World!" % now())
|
||||
|
||||
return drive_clk, say_hello
|
||||
|
||||
|
@ -1,92 +1,21 @@
|
||||
from random import randrange
|
||||
import myhdl
|
||||
from myhdl import *
|
||||
from myhdl import block, always_seq
|
||||
|
||||
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
|
||||
@block
|
||||
def inc(count, enable, clock, reset):
|
||||
|
||||
def Inc(count, enable, clock, reset):
|
||||
|
||||
""" Incrementer with enable.
|
||||
|
||||
|
||||
count -- output
|
||||
enable -- control input, increment when 1
|
||||
clock -- clock input
|
||||
reset -- asynchronous reset input
|
||||
n -- counter max value
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@always_seq(clock.posedge, reset=reset)
|
||||
def incLogic():
|
||||
def seq():
|
||||
if enable:
|
||||
count.next = count + 1
|
||||
|
||||
return incLogic
|
||||
|
||||
|
||||
def testbench():
|
||||
m = 3
|
||||
count = Signal(modbv(0)[m:])
|
||||
enable = Signal(bool(0))
|
||||
clock = Signal(bool(0))
|
||||
reset = ResetSignal(0, active=0, async=True)
|
||||
|
||||
inc_1 = Inc(count, enable, clock, reset)
|
||||
|
||||
HALF_PERIOD = delay(10)
|
||||
|
||||
@always(HALF_PERIOD)
|
||||
def clockGen():
|
||||
clock.next = not clock
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
reset.next = ACTIVE_LOW
|
||||
yield clock.negedge
|
||||
reset.next = INACTIVE_HIGH
|
||||
for i in range(20):
|
||||
enable.next = min(1, randrange(3))
|
||||
yield clock.negedge
|
||||
raise StopSimulation
|
||||
|
||||
@instance
|
||||
def monitor():
|
||||
print "enable count"
|
||||
yield reset.posedge
|
||||
while 1:
|
||||
yield clock.posedge
|
||||
yield delay(1)
|
||||
print " %s %s" % (enable, count)
|
||||
|
||||
return clockGen, stimulus, inc_1, monitor
|
||||
|
||||
tb = testbench()
|
||||
|
||||
def main():
|
||||
Simulation(tb).run()
|
||||
|
||||
|
||||
# conversion
|
||||
m = 8
|
||||
|
||||
count = Signal(modbv(0)[m:])
|
||||
enable = Signal(bool(0))
|
||||
clock = Signal(bool(0))
|
||||
reset = ResetSignal(0, active=0, async=True)
|
||||
|
||||
inc_inst = Inc(count, enable, clock, reset)
|
||||
inc_inst = toVerilog(Inc, count, enable, clock, reset)
|
||||
inc_inst = toVHDL(Inc, count, enable, clock, reset)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return seq
|
||||
|
@ -1,34 +1,21 @@
|
||||
from myhdl import Signal, Simulation, delay
|
||||
from myhdl import block, always_comb, Signal
|
||||
|
||||
@block
|
||||
def mux(z, a, b, sel):
|
||||
|
||||
""" Multiplexer.
|
||||
|
||||
|
||||
z -- mux output
|
||||
a, b -- data inputs
|
||||
sel -- control input: select a if asserted, otherwise b
|
||||
|
||||
"""
|
||||
while 1:
|
||||
yield a, b, sel
|
||||
|
||||
@always_comb
|
||||
def comb():
|
||||
if sel == 1:
|
||||
z.next = a
|
||||
else:
|
||||
z.next = b
|
||||
|
||||
from random import randrange
|
||||
|
||||
(z, a, b, sel) = [Signal(0) for i in range(4)]
|
||||
|
||||
MUX_1 = mux(z, a, b, sel)
|
||||
|
||||
def test():
|
||||
print "z a b sel"
|
||||
for i in range(8):
|
||||
a.next, b.next, sel.next = randrange(8), randrange(8), randrange(2)
|
||||
yield delay(10)
|
||||
print "%s %s %s %s" % (z, a, b, sel)
|
||||
|
||||
def main():
|
||||
Simulation(MUX_1, test()).run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
return comb
|
||||
|
38
example/manual/test_fsm.py
Normal file
38
example/manual/test_fsm.py
Normal file
@ -0,0 +1,38 @@
|
||||
import myhdl
|
||||
from myhdl import block, always, instance, Signal, ResetSignal, delay, StopSimulation
|
||||
from fsm import framer_ctrl, t_state
|
||||
|
||||
ACTIVE_LOW = 0
|
||||
|
||||
@block
|
||||
def testbench():
|
||||
|
||||
sof = Signal(bool(0))
|
||||
sync_flag = Signal(bool(0))
|
||||
clk = Signal(bool(0))
|
||||
reset_n = ResetSignal(1, active=ACTIVE_LOW, async=True)
|
||||
state = Signal(t_state.SEARCH)
|
||||
|
||||
frame_ctrl_0 = framer_ctrl(sof, state, sync_flag, clk, reset_n)
|
||||
|
||||
@always(delay(10))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
for i in range(3):
|
||||
yield clk.negedge
|
||||
for n in (12, 8, 8, 4):
|
||||
sync_flag.next = 1
|
||||
yield clk.negedge
|
||||
sync_flag.next = 0
|
||||
for i in range(n-1):
|
||||
yield clk.negedge
|
||||
raise StopSimulation()
|
||||
|
||||
return frame_ctrl_0, clkgen, stimulus
|
||||
|
||||
tb = testbench()
|
||||
tb.config_sim(trace=True)
|
||||
tb.run_sim()
|
49
example/manual/test_inc.py
Normal file
49
example/manual/test_inc.py
Normal file
@ -0,0 +1,49 @@
|
||||
import random
|
||||
from myhdl import block, always, instance, Signal, modbv, \
|
||||
ResetSignal, delay, StopSimulation
|
||||
from inc import inc
|
||||
|
||||
random.seed(1)
|
||||
randrange = random.randrange
|
||||
|
||||
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
|
||||
|
||||
@block
|
||||
def testbench():
|
||||
m = 3
|
||||
count = Signal(modbv(0)[m:])
|
||||
enable = Signal(bool(0))
|
||||
clock = Signal(bool(0))
|
||||
reset = ResetSignal(0, active=0, async=True)
|
||||
|
||||
inc_1 = inc(count, enable, clock, reset)
|
||||
|
||||
HALF_PERIOD = delay(10)
|
||||
|
||||
@always(HALF_PERIOD)
|
||||
def clockGen():
|
||||
clock.next = not clock
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
reset.next = ACTIVE_LOW
|
||||
yield clock.negedge
|
||||
reset.next = INACTIVE_HIGH
|
||||
for i in range(16):
|
||||
enable.next = min(1, randrange(3))
|
||||
yield clock.negedge
|
||||
raise StopSimulation()
|
||||
|
||||
@instance
|
||||
def monitor():
|
||||
print("enable count")
|
||||
yield reset.posedge
|
||||
while 1:
|
||||
yield clock.posedge
|
||||
yield delay(1)
|
||||
print(" %s %s" % (int(enable), count))
|
||||
|
||||
return clockGen, stimulus, inc_1, monitor
|
||||
|
||||
tb = testbench()
|
||||
tb.run_sim()
|
26
example/manual/test_mux.py
Normal file
26
example/manual/test_mux.py
Normal file
@ -0,0 +1,26 @@
|
||||
import random
|
||||
from myhdl import block, instance, Signal, intbv, delay
|
||||
from mux import mux
|
||||
|
||||
random.seed(5)
|
||||
randrange = random.randrange
|
||||
|
||||
@block
|
||||
def test_mux():
|
||||
|
||||
z, a, b, sel = [Signal(intbv(0)) for i in range(4)]
|
||||
|
||||
mux_1 = mux(z, a, b, sel)
|
||||
|
||||
@instance
|
||||
def stimulus():
|
||||
print("z a b sel")
|
||||
for i in range(12):
|
||||
a.next, b.next, sel.next = randrange(8), randrange(8), randrange(2)
|
||||
yield delay(10)
|
||||
print("%s %s %s %s" % (z, a, b, sel))
|
||||
|
||||
return mux_1, stimulus
|
||||
|
||||
tb = test_mux()
|
||||
tb.run_sim()
|
Loading…
x
Reference in New Issue
Block a user