from nmigen import Array, Elaboratable, Module, Record, Signal
from nmigen.hdl.rec import DIR_FANIN, DIR_FANOUT, DIR_NONE
from nmigen.lib.coding import PriorityEncoder
+from nmigen.utils import log2_int
-__all__ = ["Cycle", "wishbone_layout", "WishboneArbiter"]
+__all__ = ["Cycle", "make_wb_layout", "WishboneArbiter"]
class Cycle:
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)
-]
+def make_wb_layout(spec, cti=True):
+ addr_wid, mask_wid, data_wid = spec.addr_wid, spec.mask_wid, spec.reg_wid
+ adr_lsbs = log2_int(mask_wid) # LSBs of addr covered by mask
+ badwid = spec.addr_wid-adr_lsbs # MSBs (not covered by mask)
+
+ res = [
+ ("adr", badwid , DIR_FANOUT),
+ ("dat_w", data_wid, DIR_FANOUT),
+ ("dat_r", data_wid, DIR_FANIN),
+ ("sel", mask_wid, DIR_FANOUT),
+ ("cyc", 1, DIR_FANOUT),
+ ("stb", 1, DIR_FANOUT),
+ ("ack", 1, DIR_FANIN),
+ ("we", 1, DIR_FANOUT),
+ ("err", 1, DIR_FANIN)
+ ]
+ if not cti:
+ return res
+ return res + [
+ ("cti", 3, DIR_FANOUT),
+ ("bte", 2, DIR_FANOUT),
+ ]
class WishboneArbiter(Elaboratable):
- def __init__(self):
- self.bus = Record(wishbone_layout)
+ def __init__(self, pspec):
+ self.bus = Record(make_wb_layout(pspec))
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))
+ 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)