riscv-formal-nmigen/rvfi/cores/minerva/wishbone.py

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