73 lines
2.0 KiB
Python
73 lines
2.0 KiB
Python
from nmigen import *
|
|
from nmigen.hdl.rec import *
|
|
from nmigen.lib.coding import *
|
|
|
|
|
|
__all__ = ["Cycle", "wishbone_layout", "WishboneArbiter"]
|
|
|
|
|
|
class Cycle:
|
|
CLASSIC = 0
|
|
CONSTANT = 1
|
|
INCREMENT = 2
|
|
END = 7
|
|
|
|
|
|
wishbone_layout = [
|
|
("adr", 30, DIR_FANOUT),
|
|
("dat_w", 32, DIR_FANOUT),
|
|
("dat_r", 32, DIR_FANIN),
|
|
("sel", 4, DIR_FANOUT),
|
|
("cyc", 1, DIR_FANOUT),
|
|
("stb", 1, DIR_FANOUT),
|
|
("ack", 1, DIR_FANIN),
|
|
("we", 1, DIR_FANOUT),
|
|
("cti", 3, DIR_FANOUT),
|
|
("bte", 2, DIR_FANOUT),
|
|
("err", 1, DIR_FANIN)
|
|
]
|
|
|
|
|
|
class WishboneArbiter(Elaboratable):
|
|
def __init__(self):
|
|
self.bus = Record(wishbone_layout)
|
|
self._port_map = dict()
|
|
|
|
def port(self, priority):
|
|
if not isinstance(priority, int) or priority < 0:
|
|
raise TypeError("Priority must be a non-negative integer, not '{!r}'"
|
|
.format(priority))
|
|
if priority in self._port_map:
|
|
raise ValueError("Conflicting priority: '{!r}'".format(priority))
|
|
port = self._port_map[priority] = Record.like(self.bus)
|
|
return port
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
|
|
ports = [port for priority, port in sorted(self._port_map.items())]
|
|
|
|
for port in ports:
|
|
m.d.comb += port.dat_r.eq(self.bus.dat_r)
|
|
|
|
bus_pe = m.submodules.bus_pe = PriorityEncoder(len(ports))
|
|
with m.If(~self.bus.cyc):
|
|
for j, port in enumerate(ports):
|
|
m.d.sync += bus_pe.i[j].eq(port.cyc)
|
|
|
|
source = Array(ports)[bus_pe.o]
|
|
m.d.comb += [
|
|
self.bus.adr.eq(source.adr),
|
|
self.bus.dat_w.eq(source.dat_w),
|
|
self.bus.sel.eq(source.sel),
|
|
self.bus.cyc.eq(source.cyc),
|
|
self.bus.stb.eq(source.stb),
|
|
self.bus.we.eq(source.we),
|
|
self.bus.cti.eq(source.cti),
|
|
self.bus.bte.eq(source.bte),
|
|
source.ack.eq(self.bus.ack),
|
|
source.err.eq(self.bus.err)
|
|
]
|
|
|
|
return m
|