Waveforms are the classic method to verify HDL circuits
import py4hw
class Example(py4hw.Logic):
def __init__(self, parent, name, a, r):
super().__init__(parent, name)
self.a = self.addIn('a', a)
self.r = self.addOut('r', r)
self.state = 0
def clock(self):
if (self.state == 0):
if (self.a.get()):
self.state = 1
elif (self.state == 1):
if (self.a.get()):
self.state = 2
else:
self.state = 0
elif (self.state == 2):
if (self.a.get()):
self.state = 3
self.r.prepare(1)
else:
self.state = 0
else:
self.r.prepare(0)
self.state = 0
sys = py4hw.HWSystem()
a = sys.wire('a')
r = sys.wire('r')
py4hw.Sequence(sys, 'a', [0, 0, 1], a)
Example(sys, 'ex', a, r)
wvf = py4hw.Waveform(sys, 'wvf', [a,r])
sys.getSimulator().clk(20)
wvf.draw_wavedrom()
This is very convenient, but is limited to analyze the values of the wires. Can we improve it ?
The field inspector object can be used to add other elements to the waveform. For instance, the state of a State machine.
sys = py4hw.HWSystem()
a = sys.wire('a')
r = sys.wire('r')
py4hw.Sequence(sys, 'a', [0, 0, 1, 1,0,1,1,1], a)
dut = Example(sys, 'ex', a, r)
wvf = py4hw.Waveform(sys, 'wvf', [a,r, py4hw.FieldInspector(dut, 'state')])
sys.getSimulator().clk(20)
wvf.draw_wavedrom()
A typical escenario is that you want to observe all wires of a certain circuit. You can use the py4hw.debug.getPorts method to obtain the list of all ports to pass to the waveform object.
sys = py4hw.HWSystem()
a = sys.wire('a')
r = sys.wire('r')
py4hw.Sequence(sys, 'a', [0, 0, 1, 0, 1, 1, 1], a)
dut = Example(sys, 'ex', a, r)
wvf = py4hw.Waveform(sys, 'wvf', py4hw.debug.getPorts(dut))
sys.getSimulator().clk(20)
wvf.draw_wavedrom()