1 from nmigen
import Array
, Elaboratable
, Module
, Record
, Signal
2 from nmigen
.hdl
.rec
import DIR_FANIN
, DIR_FANOUT
, DIR_NONE
3 from nmigen
.lib
.coding
import PriorityEncoder
4 from nmigen
.utils
import log2_int
7 __all__
= ["Cycle", "make_wb_layout", "WishboneArbiter"]
17 def make_wb_layout(spec
, cti
=True):
18 addr_wid
, mask_wid
, data_wid
= spec
.addr_wid
, spec
.mask_wid
, spec
.reg_wid
19 adr_lsbs
= log2_int(mask_wid
) # LSBs of addr covered by mask
20 badwid
= spec
.addr_wid
-adr_lsbs
# MSBs (not covered by mask)
23 ("adr", badwid
, DIR_FANOUT
),
24 ("dat_w", data_wid
, DIR_FANOUT
),
25 ("dat_r", data_wid
, DIR_FANIN
),
26 ("sel", mask_wid
, DIR_FANOUT
),
27 ("cyc", 1, DIR_FANOUT
),
28 ("stb", 1, DIR_FANOUT
),
29 ("ack", 1, DIR_FANIN
),
30 ("we", 1, DIR_FANOUT
),
36 ("cti", 3, DIR_FANOUT
),
37 ("bte", 2, DIR_FANOUT
),
41 class WishboneArbiter(Elaboratable
):
42 def __init__(self
, pspec
):
43 self
.bus
= Record(make_wb_layout(pspec
))
44 self
._port
_map
= dict()
46 def port(self
, priority
):
47 if not isinstance(priority
, int) or priority
< 0:
48 raise TypeError("Priority must be a non-negative "\
49 "integer, not '{!r}'" .format(priority
))
50 if priority
in self
._port
_map
:
51 raise ValueError("Conflicting priority: '{!r}'".format(priority
))
52 port
= self
._port
_map
[priority
] = Record
.like(self
.bus
)
55 def elaborate(self
, platform
):
58 ports
= [port
for priority
, port
in sorted(self
._port
_map
.items())]
61 m
.d
.comb
+= port
.dat_r
.eq(self
.bus
.dat_r
)
63 bus_pe
= m
.submodules
.bus_pe
= PriorityEncoder(len(ports
))
64 with m
.If(~self
.bus
.cyc
):
65 for j
, port
in enumerate(ports
):
66 m
.d
.sync
+= bus_pe
.i
[j
].eq(port
.cyc
)
68 source
= Array(ports
)[bus_pe
.o
]
70 self
.bus
.adr
.eq(source
.adr
),
71 self
.bus
.dat_w
.eq(source
.dat_w
),
72 self
.bus
.sel
.eq(source
.sel
),
73 self
.bus
.cyc
.eq(source
.cyc
),
74 self
.bus
.stb
.eq(source
.stb
),
75 self
.bus
.we
.eq(source
.we
),
76 self
.bus
.cti
.eq(source
.cti
),
77 self
.bus
.bte
.eq(source
.bte
),
78 source
.ack
.eq(self
.bus
.ack
),
79 source
.err
.eq(self
.bus
.err
)