MyHDL Quick Reference
Hardware in Python: signals, clocked and combinational logic, simulation and conversion, in one page.
Try any of this live in the MyHDL playground.
Block skeleton
A hardware block is a function decorated with @block that returns every
generator it defines.
from myhdl import (block, Signal, intbv, modbv, always_seq, always_comb,
always, instance, delay, StopSimulation)
@block
def counter(clk, rst, en, count):
@always_seq(clk.posedge, reset=rst)
def logic():
if en:
count.next = count + 1
return logic # return the generator(s), or nothing runs
The generators that matter
@always_seq(clk.posedge, reset=rst) # clocked flip-flops, with reset
def seq():
q.next = d
@always_comb # combinational, sensitivity inferred
def comb():
y.next = a & b
@always(clk.posedge, rst.negedge) # explicit sensitivity list
def proc():
...
@instance # free-running process (testbenches)
def stim():
yield delay(10)
...
Signals and types
clk = Signal(bool(0)) # 1-bit
bus = Signal(intbv(0)[8:]) # 8-bit unsigned; [8:] sets the width
sig = Signal(intbv(0, min=-128, max=128)) # signed, from its range
cnt = Signal(modbv(0)[4:]) # modbv wraps around (no overflow error)
bus.next = 5 # schedule an update (applies next delta)
v = int(bus) # read the current value
hi = bus[7] # index a bit
nib = bus[8:4] # slice bits [7:4]
Simulation
@block
def bench():
clk = Signal(bool(0))
count = Signal(intbv(0)[4:])
dut = counter(clk, rst, en, count)
@always(delay(5)) # a clock: toggles every 5 time units
def clkgen():
clk.next = not clk
@instance
def stim():
yield delay(100)
raise StopSimulation # end the run, or it never stops
return dut, clkgen, stim
bench().config_sim(trace=True) # writes bench.vcd for the waveform
bench().run_sim()
Convert to Verilog or VHDL
The same block both simulates and converts to synthesizable HDL:
counter(clk, rst, en, count).convert(hdl='Verilog') # -> counter.v
counter(clk, rst, en, count).convert(hdl='VHDL') # -> counter.vhd
Gotchas
- Assign signals with
.next, never=(plain=just rebinds the Python name). - Return every generator from a
@block; an unreturned one silently does nothing. - End the stimulus with
raise StopSimulationor a boundeddelay, or the sim runs forever. config_sim(trace=True)is what produces the VCD you see in the playground.- Read a
Signalwithint(sig)(or use it directly in expressions); write withsig.next.