Most basic
==========
-.. include:: ../examples/basic_sim.py
+.. include:: ../examples/sim/basic1.py
:code: python
A few more features
===================
-.. include:: ../examples/basic2_sim.py
+.. include:: ../examples/sim/basic2.py
:code: python
Memory access
=============
-.. include:: ../examples/memory_sim.py
+.. include:: ../examples/sim/memory.py
:code: python
A FIR filter
============
-.. include:: ../examples/fir.py
+.. include:: ../examples/sim/fir.py
:code: python
Abstract bus transactions
=========================
-.. include:: ../examples/abstract_transactions.py
+.. include:: ../examples/sim/abstract_transactions.py
+ :code: python
+
+Dataflow simulation actors
+==========================
+.. include:: ../examples/sim/dataflow.py
:code: python
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-from random import Random
-
-from migen.fhdl.structure import *
-from migen.fhdl import autofragment
-from migen.bus.transactions import *
-from migen.bus import wishbone, asmibus
-from migen.sim.generic import Simulator
-from migen.sim.icarus import Runner
-
-# 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 MyModel:
- def read(self, address):
- return address + 4
-
-class MyModelWB(MyModel, wishbone.TargetModel):
- def __init__(self):
- self.prng = Random(763627)
-
- def can_ack(self, bus):
- # Simulate variable latency.
- return self.prng.randrange(0, 2)
-
-class MyModelASMI(MyModel, asmibus.TargetModel):
- pass
-
-def test_wishbone():
- print("*** Wishbone test")
-
- # The "wishbone.Initiator" library component runs our generator
- # and manipulates the bus signals accordingly.
- master = wishbone.Initiator(my_generator())
- # The "wishbone.Target" library component examines the bus signals
- # and calls into our model object.
- slave = wishbone.Target(MyModelWB())
- # The "wishbone.Tap" library component examines the bus at the slave port
- # and displays the transactions on the console (<TRead...>/<TWrite...>).
- tap = wishbone.Tap(slave.bus)
- # Connect the master to the slave.
- intercon = wishbone.InterconnectPointToPoint(master.bus, slave.bus)
- # A small extra simulation function to terminate the process when
- # the initiator is done (i.e. our generator is exhausted).
- def end_simulation(s):
- s.interrupt = master.done
- fragment = autofragment.from_local() + Fragment(sim=[end_simulation])
- sim = Simulator(fragment, Runner())
- sim.run()
-
-def test_asmi():
- print("*** ASMI test")
-
- # Create a hub with one port for our initiator.
- hub = asmibus.Hub(32, 32)
- port = hub.get_port()
- hub.finalize()
- # Create the initiator, target and tap (similar to the Wishbone case).
- master = asmibus.Initiator(port, my_generator())
- slave = asmibus.Target(hub, MyModelASMI())
- tap = asmibus.Tap(hub)
- # Run the simulation (same as the Wishbone case).
- def end_simulation(s):
- s.interrupt = master.done
- fragment = autofragment.from_local() + Fragment(sim=[end_simulation])
- sim = Simulator(fragment, Runner())
- sim.run()
-
-test_wishbone()
-test_asmi()
-
-# Output:
-# <TWrite adr:0x0 dat:0x0>
-# Wrote in 0 cycle(s)
-# <TWrite adr:0x1 dat:0x2>
-# Wrote in 0 cycle(s)
-# <TWrite adr:0x2 dat:0x4>
-# Wrote in 0 cycle(s)
-# <TWrite adr:0x3 dat:0x6>
-# Wrote in 1 cycle(s)
-# <TWrite adr:0x4 dat:0x8>
-# Wrote in 1 cycle(s)
-# <TWrite adr:0x5 dat:0xa>
-# Wrote in 2 cycle(s)
-# ...
-# <TRead adr:0x0 dat:0x4>
-# Read 4 in 2 cycle(s)
-# <TRead adr:0x1 dat:0x5>
-# Read 5 in 2 cycle(s)
-# <TRead adr:0x2 dat:0x6>
-# Read 6 in 1 cycle(s)
-# <TRead adr:0x3 dat:0x7>
-# Read 7 in 1 cycle(s)
-# ...
--- /dev/null
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+from migen.corelogic.fsm import FSM
+
+s = Signal()
+myfsm = FSM("FOO", "BAR")
+myfsm.act(myfsm.FOO, s.eq(1), myfsm.next_state(myfsm.BAR))
+myfsm.act(myfsm.BAR, s.eq(0), myfsm.next_state(myfsm.FOO))
+print(verilog.convert(myfsm.get_fragment(), {s}))
--- /dev/null
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+
+class LM32:
+ def __init__(self):
+ self.inst = Instance("lm32_top",
+ [("I_ADR_O", BV(32)),
+ ("I_DAT_O", BV(32)),
+ ("I_SEL_O", BV(4)),
+ ("I_CYC_O", BV(1)),
+ ("I_STB_O", BV(1)),
+ ("I_WE_O", BV(1)),
+ ("I_CTI_O", BV(3)),
+ ("I_LOCK_O", BV(1)),
+ ("I_BTE_O", BV(1)),
+ ("D_ADR_O", BV(32)),
+ ("D_DAT_O", BV(32)),
+ ("D_SEL_O", BV(4)),
+ ("D_CYC_O", BV(1)),
+ ("D_STB_O", BV(1)),
+ ("D_WE_O", BV(1)),
+ ("D_CTI_O", BV(3)),
+ ("D_LOCK_O", BV(1)),
+ ("D_BTE_O", BV(1))],
+ [("interrupt", BV(32)),
+ ("ext_break", BV(1)),
+ ("I_DAT_I", BV(32)),
+ ("I_ACK_I", BV(1)),
+ ("I_ERR_I", BV(1)),
+ ("I_RTY_I", BV(1)),
+ ("D_DAT_I", BV(32)),
+ ("D_ACK_I", BV(1)),
+ ("D_ERR_I", BV(1)),
+ ("D_RTY_I", BV(1))],
+ clkport="clk_i",
+ rstport="rst_i",
+ name="lm32")
+
+ def get_fragment(self):
+ return Fragment(instances=[self.inst])
+
+cpus = [LM32() for i in range(4)]
+frag = Fragment()
+for cpu in cpus:
+ frag += cpu.get_fragment()
+print(verilog.convert(frag, set([cpus[0].inst.ins["interrupt"], cpus[0].inst.outs["I_WE_O"]])))
--- /dev/null
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+
+d = 100
+d_b = bits_for(d-1)
+w = 32
+
+a1 = Signal(BV(d_b))
+d1 = Signal(BV(w))
+we1 = Signal(BV(4))
+dw1 = Signal(BV(w))
+re = Signal()
+p1 = MemoryPort(a1, d1, we1, dw1, we_granularity=8)
+
+a2 = Signal(BV(d_b))
+d2 = Signal(BV(w))
+re2 = Signal()
+p2 = MemoryPort(a2, d2, re=re2)
+
+mem = Memory(w, d, p1, p2, init=[5, 18, 32])
+f = Fragment(memories=[mem])
+v = verilog.convert(f, ios={a1, d1, we1, dw1, a2, d2, re2})
+print(v)
--- /dev/null
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+from migen.bank import description, csrgen
+from migen.bank.description import READ_ONLY, WRITE_ONLY
+
+ninputs = 32
+noutputs = 32
+
+oreg = description.RegisterField("o", noutputs)
+ireg = description.RegisterField("i", ninputs, READ_ONLY, WRITE_ONLY)
+
+# input path
+gpio_in = Signal(BV(ninputs))
+gpio_in_s = Signal(BV(ninputs)) # synchronizer
+insync = [gpio_in_s.eq(gpio_in), ireg.field.w.eq(gpio_in_s)]
+inf = Fragment(sync=insync)
+
+bank = csrgen.Bank([oreg, ireg])
+f = bank.get_fragment() + inf
+oreg.field.r.name_override = "gpio_out"
+i = bank.interface
+v = verilog.convert(f, {i.dat_r, oreg.field.r, i.adr, i.we, i.dat_w, gpio_in})
+print(v)
--- /dev/null
+from migen.fhdl import verilog
+from migen.corelogic import divider
+
+d1 = divider.Divider(16)
+d2 = divider.Divider(16)
+frag = d1.get_fragment() + d2.get_fragment()
+o = verilog.convert(frag, {
+ d1.ready_o, d1.quotient_o, d1.remainder_o, d1.start_i, d1.dividend_i, d1.divisor_i,
+ d2.ready_o, d2.quotient_o, d2.remainder_o, d2.start_i, d2.dividend_i, d2.divisor_i})
+print(o)
--- /dev/null
+from migen.fhdl.structure import *
+from migen.corelogic.record import *
+
+L = [
+ ("x", BV(10), 8),
+ ("y", BV(10), 8),
+ ("level2", [
+ ("a", BV(5), 32),
+ ("b", BV(5), 16)
+ ])
+]
+
+myrec = Record(L)
+print(myrec.flatten())
+print(myrec.flatten(True))
+s = myrec.subrecord("level2/a", "x")
+print(s.flatten())
+print(s.level2.layout())
+myrec2 = myrec.copy()
+print(myrec2.flatten())
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-from migen.fhdl.structure import *
-from migen.sim.generic import Simulator, TopLevel
-from migen.sim.icarus import Runner
-
-# A slightly improved counter.
-# Has a clock enable (CE) signal, counts on more bits
-# and resets with a negative number.
-class Counter:
- def __init__(self):
- self.ce = Signal()
- # Demonstrate negative numbers and signals larger than 32 bits.
- self.count = Signal(BV(37, True), reset=-5)
-
- def do_simulation(self, s):
- # Only assert CE every second cycle.
- # => each counter value is held for two cycles.
- if s.cycle_counter % 2:
- s.wr(self.ce, 0) # This is how you write to a signal.
- else:
- s.wr(self.ce, 1)
- print("Cycle: " + str(s.cycle_counter) + " Count: " + \
- str(s.rd(self.count)))
- # Set the "initialize" property on our simulation function.
- # The simulator will call it during the reset cycle,
- # with s.cycle_counter == -1.
- do_simulation.initialize = True
-
- # Output is:
- # Cycle: -1 Count: 0
- # Cycle: 0 Count: -5
- # Cycle: 1 Count: -5
- # Cycle: 2 Count: -4
- # Cycle: 3 Count: -4
- # Cycle: 4 Count: -3
- # ...
-
- def get_fragment(self):
- sync = [If(self.ce, self.count.eq(self.count + 1))]
- sim = [self.do_simulation]
- return Fragment(sync=sync, sim=sim)
-
-def main():
- dut = Counter()
- # Instantiating the generic top-level ourselves lets us
- # specify a VCD output file.
- sim = Simulator(dut.get_fragment(), Runner(), TopLevel("my.vcd"))
- sim.run(20)
-
-main()
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-from migen.fhdl.structure import *
-from migen.sim.generic import Simulator
-from migen.sim.icarus import Runner
-
-# Our simple counter, which increments at every cycle
-# and prints its current value in simulation.
-class Counter:
- def __init__(self):
- self.count = Signal(BV(4))
-
- # This function will be called at every cycle.
- def do_simulation(self, s):
- # Simply read the count signal and print it.
- # The output is:
- # Count: 0
- # Count: 1
- # Count: 2
- # ...
- print("Count: " + str(s.rd(self.count)))
-
- def get_fragment(self):
- # At each cycle, increase the value of the count signal.
- # We do it with convertible/synthesizable FHDL code.
- sync = [self.count.eq(self.count + 1)]
- # List our simulation function in the fragment.
- sim = [self.do_simulation]
- return Fragment(sync=sync, sim=sim)
-
-def main():
- dut = Counter()
- # Use the Icarus Verilog runner.
- # We do not specify a top-level object, and use the default.
- sim = Simulator(dut.get_fragment(), Runner())
- # Since we do not use sim.interrupt, limit the simulation
- # to some number of cycles.
- sim.run(20)
-
-main()
+++ /dev/null
-from migen.fhdl import verilog
-from migen.corelogic import divider
-
-d1 = divider.Divider(16)
-d2 = divider.Divider(16)
-frag = d1.get_fragment() + d2.get_fragment()
-o = verilog.convert(frag, {
- d1.ready_o, d1.quotient_o, d1.remainder_o, d1.start_i, d1.dividend_i, d1.divisor_i,
- d2.ready_o, d2.quotient_o, d2.remainder_o, d2.start_i, d2.dividend_i, d2.divisor_i})
-print(o)
+++ /dev/null
-import sys
-
-from migen.fhdl import verilog
-from migen.flow.ala import *
-from migen.flow.network import *
-from migen.flow.composer import *
-
-g = DataFlowGraph()
-a1 = make_composable(g, Add(BV(16)))
-a2 = make_composable(g, Add(BV(16)))
-a3 = make_composable(g, Add(BV(16)))
-c3 = (a1 + a2)*a3
-c = CompositeActor(g)
-
-frag = c.get_fragment()
-
-print(verilog.convert(frag))
-
-if len(sys.argv) > 1 and sys.argv[1] == "draw":
- import matplotlib.pyplot as plt
- import networkx as nx
- nx.draw(g)
- plt.show()
--- /dev/null
+import sys
+
+from migen.fhdl import verilog
+from migen.flow.ala import *
+from migen.flow.network import *
+from migen.flow.composer import *
+
+g = DataFlowGraph()
+a1 = make_composable(g, Add(BV(16)))
+a2 = make_composable(g, Add(BV(16)))
+a3 = make_composable(g, Add(BV(16)))
+c3 = (a1 + a2)*a3
+c = CompositeActor(g)
+
+frag = c.get_fragment()
+
+print(verilog.convert(frag))
+
+if len(sys.argv) > 1 and sys.argv[1] == "draw":
+ import matplotlib.pyplot as plt
+ import networkx as nx
+ nx.draw(g)
+ plt.show()
--- /dev/null
+from random import Random
+
+from migen.fhdl import verilog
+from migen.flow.ala import *
+from migen.flow.network import *
+from migen.actorlib import dma_wishbone
+from migen.actorlib.sim import *
+from migen.bus import wishbone
+from migen.sim.generic import Simulator
+from migen.sim.icarus import Runner
+
+class MyModel(wishbone.TargetModel):
+ def __init__(self):
+ self.prng = Random(763627)
+
+ def read(self, address):
+ return address + 4
+
+ def can_ack(self, bus):
+ return self.prng.randrange(0, 2)
+
+def adrgen_gen():
+ for i in range(10):
+ print("Address: " + str(i))
+ yield Token("address", {"a": i})
+
+def dumper_gen():
+ while True:
+ t = Token("data")
+ yield t
+ print("Received: " + str(t.value["d"]))
+
+def test_reader():
+ print("*** Testing reader")
+ adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", BV(30))]))
+ reader = dma_wishbone.Reader()
+ dumper = SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))]))
+ g = DataFlowGraph()
+ g.add_connection(adrgen, reader)
+ g.add_connection(reader, dumper)
+ comp = CompositeActor(g)
+
+ peripheral = wishbone.Target(MyModel())
+ interconnect = wishbone.InterconnectPointToPoint(reader.bus, peripheral.bus)
+
+ def end_simulation(s):
+ s.interrupt = adrgen.done and not s.rd(comp.busy)
+
+ fragment = comp.get_fragment() \
+ + peripheral.get_fragment() \
+ + interconnect.get_fragment() \
+ + Fragment(sim=[end_simulation])
+
+ sim = Simulator(fragment, Runner())
+ sim.run()
+
+def trgen_gen():
+ for i in range(10):
+ a = i
+ d = i+10
+ print("Address: " + str(a) + " Data: " + str(d))
+ yield Token("address_data", {"a": a, "d": d})
+
+def test_writer():
+ print("*** Testing writer")
+ trgen = SimActor(trgen_gen(), ("address_data", Source, [("a", BV(30)), ("d", BV(32))]))
+ writer = dma_wishbone.Writer()
+ g = DataFlowGraph()
+ g.add_connection(trgen, writer)
+ comp = CompositeActor(g)
+
+ peripheral = wishbone.Target(MyModel())
+ tap = wishbone.Tap(peripheral.bus)
+ interconnect = wishbone.InterconnectPointToPoint(writer.bus, peripheral.bus)
+
+ def end_simulation(s):
+ s.interrupt = trgen.done and not s.rd(comp.busy)
+
+ fragment = comp.get_fragment() \
+ + peripheral.get_fragment() \
+ + tap.get_fragment() \
+ + interconnect.get_fragment() \
+ + Fragment(sim=[end_simulation])
+
+ sim = Simulator(fragment, Runner())
+ sim.run()
+
+test_reader()
+test_writer()
+++ /dev/null
-from random import Random
-
-from migen.fhdl import verilog
-from migen.flow.ala import *
-from migen.flow.network import *
-from migen.actorlib import dma_wishbone
-from migen.actorlib.sim import *
-from migen.bus import wishbone
-from migen.sim.generic import Simulator
-from migen.sim.icarus import Runner
-
-class MyModel(wishbone.TargetModel):
- def __init__(self):
- self.prng = Random(763627)
-
- def read(self, address):
- return address + 4
-
- def can_ack(self, bus):
- return self.prng.randrange(0, 2)
-
-def adrgen_gen():
- for i in range(10):
- print("Address: " + str(i))
- yield Token("address", {"a": i})
-
-def dumper_gen():
- while True:
- t = Token("data")
- yield t
- print("Received: " + str(t.value["d"]))
-
-def test_reader():
- print("*** Testing reader")
- adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", BV(30))]))
- reader = dma_wishbone.Reader()
- dumper = SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))]))
- g = DataFlowGraph()
- g.add_connection(adrgen, reader)
- g.add_connection(reader, dumper)
- comp = CompositeActor(g)
-
- peripheral = wishbone.Target(MyModel())
- interconnect = wishbone.InterconnectPointToPoint(reader.bus, peripheral.bus)
-
- def end_simulation(s):
- s.interrupt = adrgen.done and not s.rd(comp.busy)
-
- fragment = comp.get_fragment() \
- + peripheral.get_fragment() \
- + interconnect.get_fragment() \
- + Fragment(sim=[end_simulation])
-
- sim = Simulator(fragment, Runner())
- sim.run()
-
-def trgen_gen():
- for i in range(10):
- a = i
- d = i+10
- print("Address: " + str(a) + " Data: " + str(d))
- yield Token("address_data", {"a": a, "d": d})
-
-def test_writer():
- print("*** Testing writer")
- trgen = SimActor(trgen_gen(), ("address_data", Source, [("a", BV(30)), ("d", BV(32))]))
- writer = dma_wishbone.Writer()
- g = DataFlowGraph()
- g.add_connection(trgen, writer)
- comp = CompositeActor(g)
-
- peripheral = wishbone.Target(MyModel())
- tap = wishbone.Tap(peripheral.bus)
- interconnect = wishbone.InterconnectPointToPoint(writer.bus, peripheral.bus)
-
- def end_simulation(s):
- s.interrupt = trgen.done and not s.rd(comp.busy)
-
- fragment = comp.get_fragment() \
- + peripheral.get_fragment() \
- + tap.get_fragment() \
- + interconnect.get_fragment() \
- + Fragment(sim=[end_simulation])
-
- sim = Simulator(fragment, Runner())
- sim.run()
-
-test_reader()
-test_writer()
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.flow.actor import *
-from migen.flow.network import *
-from migen.actorlib.sim import *
-from migen.sim.generic import Simulator
-from migen.sim.icarus import Runner
-
-def source_gen():
- for i in range(10):
- print("Sending: " + str(i))
- yield Token("source", {"value": i})
-
-def sink_gen():
- while True:
- t = Token("sink")
- yield t
- print("Received: " + str(t.value["value"]))
-
-def main():
- source = SimActor(source_gen(), ("source", Source, [("value", BV(32))]))
- sink = SimActor(sink_gen(), ("sink", Sink, [("value", BV(32))]))
- g = DataFlowGraph()
- g.add_connection(source, sink)
- comp = CompositeActor(g)
- def end_simulation(s):
- s.interrupt = source.done
- fragment = comp.get_fragment() + Fragment(sim=[end_simulation])
- sim = Simulator(fragment, Runner())
- sim.run()
-
-main()
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-from math import cos, pi
-from scipy import signal
-import matplotlib.pyplot as plt
-
-from migen.fhdl.structure import *
-from migen.fhdl import verilog
-from migen.corelogic.misc import optree
-from migen.fhdl import autofragment
-from migen.sim.generic import Simulator, PureSimulable
-from migen.sim.icarus import Runner
-
-# A synthesizable FIR filter.
-class FIR:
- def __init__(self, coef, wsize=16):
- self.coef = coef
- self.wsize = wsize
- self.i = Signal(BV(self.wsize, True))
- self.o = Signal(BV(self.wsize, True))
-
- def get_fragment(self):
- muls = []
- sync = []
- src = self.i
- for c in self.coef:
- sreg = Signal(BV(self.wsize, True))
- sync.append(sreg.eq(src))
- src = sreg
- c_fp = int(c*2**(self.wsize - 1))
- c_e = Constant(c_fp, BV(bits_for(c_fp), True))
- muls.append(c_e*sreg)
- sum_full = Signal(BV(2*self.wsize-1, True))
- sync.append(sum_full.eq(optree("+", muls)))
- comb = [self.o.eq(sum_full[self.wsize-1:])]
- return Fragment(comb, sync)
-
-# A test bench for our FIR filter.
-# Generates a sine wave at the input and records the output.
-class TB(PureSimulable):
- def __init__(self, fir, frequency):
- self.fir = fir
- self.frequency = frequency
- self.inputs = []
- self.outputs = []
-
- def do_simulation(self, s):
- f = 2**(self.fir.wsize - 1)
- v = 0.1*cos(2*pi*self.frequency*s.cycle_counter)
- s.wr(self.fir.i, int(f*v))
- self.inputs.append(v)
- self.outputs.append(s.rd(self.fir.o)/f)
-
-def main():
- # Compute filter coefficients with SciPy.
- coef = signal.remez(80, [0, 0.1, 0.1, 0.5], [1, 0])
- fir = FIR(coef)
-
- # Simulate for different frequencies and concatenate
- # the results.
- in_signals = []
- out_signals = []
- for frequency in [0.05, 0.07, 0.1, 0.15, 0.2]:
- tb = TB(fir, frequency)
- fragment = autofragment.from_local()
- sim = Simulator(fragment, Runner())
- sim.run(100)
- in_signals += tb.inputs
- out_signals += tb.outputs
-
- # Plot data from the input and output waveforms.
- plt.plot(in_signals)
- plt.plot(out_signals)
- plt.show()
-
- # Print the Verilog source for the filter.
- print(verilog.convert(fir.get_fragment(),
- ios={fir.i, fir.o}))
-
-main()
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.fhdl import verilog
-from migen.corelogic.fsm import FSM
-
-s = Signal()
-myfsm = FSM("FOO", "BAR")
-myfsm.act(myfsm.FOO, s.eq(1), myfsm.next_state(myfsm.BAR))
-myfsm.act(myfsm.BAR, s.eq(0), myfsm.next_state(myfsm.FOO))
-print(verilog.convert(myfsm.get_fragment(), {s}))
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.fhdl import verilog
-
-class LM32:
- def __init__(self):
- self.inst = Instance("lm32_top",
- [("I_ADR_O", BV(32)),
- ("I_DAT_O", BV(32)),
- ("I_SEL_O", BV(4)),
- ("I_CYC_O", BV(1)),
- ("I_STB_O", BV(1)),
- ("I_WE_O", BV(1)),
- ("I_CTI_O", BV(3)),
- ("I_LOCK_O", BV(1)),
- ("I_BTE_O", BV(1)),
- ("D_ADR_O", BV(32)),
- ("D_DAT_O", BV(32)),
- ("D_SEL_O", BV(4)),
- ("D_CYC_O", BV(1)),
- ("D_STB_O", BV(1)),
- ("D_WE_O", BV(1)),
- ("D_CTI_O", BV(3)),
- ("D_LOCK_O", BV(1)),
- ("D_BTE_O", BV(1))],
- [("interrupt", BV(32)),
- ("ext_break", BV(1)),
- ("I_DAT_I", BV(32)),
- ("I_ACK_I", BV(1)),
- ("I_ERR_I", BV(1)),
- ("I_RTY_I", BV(1)),
- ("D_DAT_I", BV(32)),
- ("D_ACK_I", BV(1)),
- ("D_ERR_I", BV(1)),
- ("D_RTY_I", BV(1))],
- clkport="clk_i",
- rstport="rst_i",
- name="lm32")
-
- def get_fragment(self):
- return Fragment(instances=[self.inst])
-
-cpus = [LM32() for i in range(4)]
-frag = Fragment()
-for cpu in cpus:
- frag += cpu.get_fragment()
-print(verilog.convert(frag, set([cpus[0].inst.ins["interrupt"], cpus[0].inst.outs["I_WE_O"]])))
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.fhdl import verilog
-
-d = 100
-d_b = bits_for(d-1)
-w = 32
-
-a1 = Signal(BV(d_b))
-d1 = Signal(BV(w))
-we1 = Signal(BV(4))
-dw1 = Signal(BV(w))
-re = Signal()
-p1 = MemoryPort(a1, d1, we1, dw1, we_granularity=8)
-
-a2 = Signal(BV(d_b))
-d2 = Signal(BV(w))
-re2 = Signal()
-p2 = MemoryPort(a2, d2, re=re2)
-
-mem = Memory(w, d, p1, p2, init=[5, 18, 32])
-f = Fragment(memories=[mem])
-v = verilog.convert(f, ios={a1, d1, we1, dw1, a2, d2, re2})
-print(v)
+++ /dev/null
-# Copyright (C) 2012 Vermeer Manufacturing Co.
-# License: GPLv3 with additional permissions (see README).
-
-from migen.fhdl.structure import *
-from migen.sim.generic import Simulator
-from migen.sim.icarus import Runner
-
-class Mem:
- def __init__(self):
- self.a = Signal(BV(12))
- self.d = Signal(BV(16))
- p = MemoryPort(self.a, self.d)
- # Initialize the beginning of the memory with integers
- # from 0 to 19.
- self.mem = Memory(16, 2**12, p, init=list(range(20)))
-
- def do_simulation(self, s):
- # Read the memory. Use the cycle counter as address.
- value = s.rd(self.mem, s.cycle_counter)
- # Print the result. Output is:
- # 0
- # 1
- # 2
- # ...
- print(value)
- # Demonstrate how to interrupt the simulator.
- if value == 10:
- s.interrupt = True
-
- def get_fragment(self):
- return Fragment(memories=[self.mem], sim=[self.do_simulation])
-
-def main():
- dut = Mem()
- sim = Simulator(dut.get_fragment(), Runner())
- # No need for a cycle limit here, we use sim.interrupt instead.
- sim.run()
-
-main()
--- /dev/null
+# Copyright (C) 2012 Vermeer Manufacturing Co.
+# License: GPLv3 with additional permissions (see README).
+
+from random import Random
+
+from migen.fhdl.structure import *
+from migen.fhdl import autofragment
+from migen.bus.transactions import *
+from migen.bus import wishbone, asmibus
+from migen.sim.generic import Simulator
+from migen.sim.icarus import Runner
+
+# 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 MyModel:
+ def read(self, address):
+ return address + 4
+
+class MyModelWB(MyModel, wishbone.TargetModel):
+ def __init__(self):
+ self.prng = Random(763627)
+
+ def can_ack(self, bus):
+ # Simulate variable latency.
+ return self.prng.randrange(0, 2)
+
+class MyModelASMI(MyModel, asmibus.TargetModel):
+ pass
+
+def test_wishbone():
+ print("*** Wishbone test")
+
+ # The "wishbone.Initiator" library component runs our generator
+ # and manipulates the bus signals accordingly.
+ master = wishbone.Initiator(my_generator())
+ # The "wishbone.Target" library component examines the bus signals
+ # and calls into our model object.
+ slave = wishbone.Target(MyModelWB())
+ # The "wishbone.Tap" library component examines the bus at the slave port
+ # and displays the transactions on the console (<TRead...>/<TWrite...>).
+ tap = wishbone.Tap(slave.bus)
+ # Connect the master to the slave.
+ intercon = wishbone.InterconnectPointToPoint(master.bus, slave.bus)
+ # A small extra simulation function to terminate the process when
+ # the initiator is done (i.e. our generator is exhausted).
+ def end_simulation(s):
+ s.interrupt = master.done
+ fragment = autofragment.from_local() + Fragment(sim=[end_simulation])
+ sim = Simulator(fragment, Runner())
+ sim.run()
+
+def test_asmi():
+ print("*** ASMI test")
+
+ # Create a hub with one port for our initiator.
+ hub = asmibus.Hub(32, 32)
+ port = hub.get_port()
+ hub.finalize()
+ # Create the initiator, target and tap (similar to the Wishbone case).
+ master = asmibus.Initiator(port, my_generator())
+ slave = asmibus.Target(hub, MyModelASMI())
+ tap = asmibus.Tap(hub)
+ # Run the simulation (same as the Wishbone case).
+ def end_simulation(s):
+ s.interrupt = master.done
+ fragment = autofragment.from_local() + Fragment(sim=[end_simulation])
+ sim = Simulator(fragment, Runner())
+ sim.run()
+
+test_wishbone()
+test_asmi()
+
+# Output:
+# <TWrite adr:0x0 dat:0x0>
+# Wrote in 0 cycle(s)
+# <TWrite adr:0x1 dat:0x2>
+# Wrote in 0 cycle(s)
+# <TWrite adr:0x2 dat:0x4>
+# Wrote in 0 cycle(s)
+# <TWrite adr:0x3 dat:0x6>
+# Wrote in 1 cycle(s)
+# <TWrite adr:0x4 dat:0x8>
+# Wrote in 1 cycle(s)
+# <TWrite adr:0x5 dat:0xa>
+# Wrote in 2 cycle(s)
+# ...
+# <TRead adr:0x0 dat:0x4>
+# Read 4 in 2 cycle(s)
+# <TRead adr:0x1 dat:0x5>
+# Read 5 in 2 cycle(s)
+# <TRead adr:0x2 dat:0x6>
+# Read 6 in 1 cycle(s)
+# <TRead adr:0x3 dat:0x7>
+# Read 7 in 1 cycle(s)
+# ...
--- /dev/null
+# Copyright (C) 2012 Vermeer Manufacturing Co.
+# License: GPLv3 with additional permissions (see README).
+
+from migen.fhdl.structure import *
+from migen.sim.generic import Simulator
+from migen.sim.icarus import Runner
+
+# Our simple counter, which increments at every cycle
+# and prints its current value in simulation.
+class Counter:
+ def __init__(self):
+ self.count = Signal(BV(4))
+
+ # This function will be called at every cycle.
+ def do_simulation(self, s):
+ # Simply read the count signal and print it.
+ # The output is:
+ # Count: 0
+ # Count: 1
+ # Count: 2
+ # ...
+ print("Count: " + str(s.rd(self.count)))
+
+ def get_fragment(self):
+ # At each cycle, increase the value of the count signal.
+ # We do it with convertible/synthesizable FHDL code.
+ sync = [self.count.eq(self.count + 1)]
+ # List our simulation function in the fragment.
+ sim = [self.do_simulation]
+ return Fragment(sync=sync, sim=sim)
+
+def main():
+ dut = Counter()
+ # Use the Icarus Verilog runner.
+ # We do not specify a top-level object, and use the default.
+ sim = Simulator(dut.get_fragment(), Runner())
+ # Since we do not use sim.interrupt, limit the simulation
+ # to some number of cycles.
+ sim.run(20)
+
+main()
--- /dev/null
+# Copyright (C) 2012 Vermeer Manufacturing Co.
+# License: GPLv3 with additional permissions (see README).
+
+from migen.fhdl.structure import *
+from migen.sim.generic import Simulator, TopLevel
+from migen.sim.icarus import Runner
+
+# A slightly improved counter.
+# Has a clock enable (CE) signal, counts on more bits
+# and resets with a negative number.
+class Counter:
+ def __init__(self):
+ self.ce = Signal()
+ # Demonstrate negative numbers and signals larger than 32 bits.
+ self.count = Signal(BV(37, True), reset=-5)
+
+ def do_simulation(self, s):
+ # Only assert CE every second cycle.
+ # => each counter value is held for two cycles.
+ if s.cycle_counter % 2:
+ s.wr(self.ce, 0) # This is how you write to a signal.
+ else:
+ s.wr(self.ce, 1)
+ print("Cycle: " + str(s.cycle_counter) + " Count: " + \
+ str(s.rd(self.count)))
+ # Set the "initialize" property on our simulation function.
+ # The simulator will call it during the reset cycle,
+ # with s.cycle_counter == -1.
+ do_simulation.initialize = True
+
+ # Output is:
+ # Cycle: -1 Count: 0
+ # Cycle: 0 Count: -5
+ # Cycle: 1 Count: -5
+ # Cycle: 2 Count: -4
+ # Cycle: 3 Count: -4
+ # Cycle: 4 Count: -3
+ # ...
+
+ def get_fragment(self):
+ sync = [If(self.ce, self.count.eq(self.count + 1))]
+ sim = [self.do_simulation]
+ return Fragment(sync=sync, sim=sim)
+
+def main():
+ dut = Counter()
+ # Instantiating the generic top-level ourselves lets us
+ # specify a VCD output file.
+ sim = Simulator(dut.get_fragment(), Runner(), TopLevel("my.vcd"))
+ sim.run(20)
+
+main()
--- /dev/null
+from migen.fhdl.structure import *
+from migen.flow.actor import *
+from migen.flow.network import *
+from migen.actorlib.sim import *
+from migen.sim.generic import Simulator
+from migen.sim.icarus import Runner
+
+def source_gen():
+ for i in range(10):
+ print("Sending: " + str(i))
+ yield Token("source", {"value": i})
+
+def sink_gen():
+ while True:
+ t = Token("sink")
+ yield t
+ print("Received: " + str(t.value["value"]))
+
+def main():
+ source = SimActor(source_gen(), ("source", Source, [("value", BV(32))]))
+ sink = SimActor(sink_gen(), ("sink", Sink, [("value", BV(32))]))
+ g = DataFlowGraph()
+ g.add_connection(source, sink)
+ comp = CompositeActor(g)
+ def end_simulation(s):
+ s.interrupt = source.done
+ fragment = comp.get_fragment() + Fragment(sim=[end_simulation])
+ sim = Simulator(fragment, Runner())
+ sim.run()
+
+main()
--- /dev/null
+# Copyright (C) 2012 Vermeer Manufacturing Co.
+# License: GPLv3 with additional permissions (see README).
+
+from math import cos, pi
+from scipy import signal
+import matplotlib.pyplot as plt
+
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+from migen.corelogic.misc import optree
+from migen.fhdl import autofragment
+from migen.sim.generic import Simulator, PureSimulable
+from migen.sim.icarus import Runner
+
+# A synthesizable FIR filter.
+class FIR:
+ def __init__(self, coef, wsize=16):
+ self.coef = coef
+ self.wsize = wsize
+ self.i = Signal(BV(self.wsize, True))
+ self.o = Signal(BV(self.wsize, True))
+
+ def get_fragment(self):
+ muls = []
+ sync = []
+ src = self.i
+ for c in self.coef:
+ sreg = Signal(BV(self.wsize, True))
+ sync.append(sreg.eq(src))
+ src = sreg
+ c_fp = int(c*2**(self.wsize - 1))
+ c_e = Constant(c_fp, BV(bits_for(c_fp), True))
+ muls.append(c_e*sreg)
+ sum_full = Signal(BV(2*self.wsize-1, True))
+ sync.append(sum_full.eq(optree("+", muls)))
+ comb = [self.o.eq(sum_full[self.wsize-1:])]
+ return Fragment(comb, sync)
+
+# A test bench for our FIR filter.
+# Generates a sine wave at the input and records the output.
+class TB(PureSimulable):
+ def __init__(self, fir, frequency):
+ self.fir = fir
+ self.frequency = frequency
+ self.inputs = []
+ self.outputs = []
+
+ def do_simulation(self, s):
+ f = 2**(self.fir.wsize - 1)
+ v = 0.1*cos(2*pi*self.frequency*s.cycle_counter)
+ s.wr(self.fir.i, int(f*v))
+ self.inputs.append(v)
+ self.outputs.append(s.rd(self.fir.o)/f)
+
+def main():
+ # Compute filter coefficients with SciPy.
+ coef = signal.remez(80, [0, 0.1, 0.1, 0.5], [1, 0])
+ fir = FIR(coef)
+
+ # Simulate for different frequencies and concatenate
+ # the results.
+ in_signals = []
+ out_signals = []
+ for frequency in [0.05, 0.07, 0.1, 0.15, 0.2]:
+ tb = TB(fir, frequency)
+ fragment = autofragment.from_local()
+ sim = Simulator(fragment, Runner())
+ sim.run(100)
+ in_signals += tb.inputs
+ out_signals += tb.outputs
+
+ # Plot data from the input and output waveforms.
+ plt.plot(in_signals)
+ plt.plot(out_signals)
+ plt.show()
+
+ # Print the Verilog source for the filter.
+ print(verilog.convert(fir.get_fragment(),
+ ios={fir.i, fir.o}))
+
+main()
--- /dev/null
+# Copyright (C) 2012 Vermeer Manufacturing Co.
+# License: GPLv3 with additional permissions (see README).
+
+from migen.fhdl.structure import *
+from migen.sim.generic import Simulator
+from migen.sim.icarus import Runner
+
+class Mem:
+ def __init__(self):
+ self.a = Signal(BV(12))
+ self.d = Signal(BV(16))
+ p = MemoryPort(self.a, self.d)
+ # Initialize the beginning of the memory with integers
+ # from 0 to 19.
+ self.mem = Memory(16, 2**12, p, init=list(range(20)))
+
+ def do_simulation(self, s):
+ # Read the memory. Use the cycle counter as address.
+ value = s.rd(self.mem, s.cycle_counter)
+ # Print the result. Output is:
+ # 0
+ # 1
+ # 2
+ # ...
+ print(value)
+ # Demonstrate how to interrupt the simulator.
+ if value == 10:
+ s.interrupt = True
+
+ def get_fragment(self):
+ return Fragment(memories=[self.mem], sim=[self.do_simulation])
+
+def main():
+ dut = Mem()
+ sim = Simulator(dut.get_fragment(), Runner())
+ # No need for a cycle limit here, we use sim.interrupt instead.
+ sim.run()
+
+main()
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.fhdl import verilog
-from migen.bank import description, csrgen
-from migen.bank.description import READ_ONLY, WRITE_ONLY
-
-ninputs = 32
-noutputs = 32
-
-oreg = description.RegisterField("o", noutputs)
-ireg = description.RegisterField("i", ninputs, READ_ONLY, WRITE_ONLY)
-
-# input path
-gpio_in = Signal(BV(ninputs))
-gpio_in_s = Signal(BV(ninputs)) # synchronizer
-insync = [gpio_in_s.eq(gpio_in), ireg.field.w.eq(gpio_in_s)]
-inf = Fragment(sync=insync)
-
-bank = csrgen.Bank([oreg, ireg])
-f = bank.get_fragment() + inf
-oreg.field.r.name_override = "gpio_out"
-i = bank.interface
-v = verilog.convert(f, {i.dat_r, oreg.field.r, i.adr, i.we, i.dat_w, gpio_in})
-print(v)
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.corelogic.record import *
-
-L = [
- ("x", BV(10), 8),
- ("y", BV(10), 8),
- ("level2", [
- ("a", BV(5), 32),
- ("b", BV(5), 16)
- ])
-]
-
-myrec = Record(L)
-print(myrec.flatten())
-print(myrec.flatten(True))
-s = myrec.subrecord("level2/a", "x")
-print(s.flatten())
-print(s.level2.layout())
-myrec2 = myrec.copy()
-print(myrec2.flatten())