from random import Random from migen.fhdl.std import * from migen.bus.transactions import * from migen.bus import wishbone from migen.sim.generic import run_simulation # Our bus master. # Python generators let us program bus transactions in an elegant sequential style. def my_generator(): prng = Random(92837) # Write to the first addresses. for x in range(10): t = TWrite(x, 2*x) yield t print("Wrote in " + str(t.latency) + " cycle(s)") # Insert some dead cycles to simulate bus inactivity. for delay in range(prng.randrange(0, 3)): yield None # Read from the first addresses. for x in range(10): t = TRead(x) yield t print("Read " + str(t.data) + " in " + str(t.latency) + " cycle(s)") for delay in range(prng.randrange(0, 3)): yield None # Our bus slave. class MyModelWB(wishbone.TargetModel): def __init__(self): self.prng = Random(763627) def read(self, address): return address + 4 def can_ack(self, bus): # Simulate variable latency. return self.prng.randrange(0, 2) class TB(Module): def __init__(self): # The "wishbone.Initiator" library component runs our generator # and manipulates the bus signals accordingly. self.submodules.master = wishbone.Initiator(my_generator()) # The "wishbone.Target" library component examines the bus signals # and calls into our model object. self.submodules.slave = wishbone.Target(MyModelWB()) # The "wishbone.Tap" library component examines the bus at the slave port # and displays the transactions on the console (/). self.submodules.tap = wishbone.Tap(self.slave.bus) # Connect the master to the slave. self.submodules.intercon = wishbone.InterconnectPointToPoint(self.master.bus, self.slave.bus) if __name__ == "__main__": run_simulation(TB()) # Output: # # Wrote in 0 cycle(s) # # Wrote in 0 cycle(s) # # Wrote in 0 cycle(s) # # Wrote in 1 cycle(s) # # Wrote in 1 cycle(s) # # Wrote in 2 cycle(s) # ... # # Read 4 in 2 cycle(s) # # Read 5 in 2 cycle(s) # # Read 6 in 1 cycle(s) # # Read 7 in 1 cycle(s) # ...