2 from nmigen
.utils
import log2_int
4 from . import Interface
as CSRInterface
5 from ..wishbone
import Interface
as WishboneInterface
8 __all__
= ["WishboneCSRBridge"]
11 class WishboneCSRBridge(Elaboratable
):
12 """Wishbone to CSR bridge.
14 A bus bridge for accessing CSR registers from Wishbone. This bridge
15 supports any Wishbone data width greater or equal to CSR data width
16 and performs appropriate address translation.
21 Reads and writes always take ``self.data_width // csr_bus.data_width +
22 1`` cycles to complete, regardless of the select inputs. Write side
23 effects occur simultaneously with acknowledgement.
27 csr_bus : :class:`..csr.Interface`
28 CSR bus driven by the bridge.
29 data_width : int or None
30 Wishbone bus data width. If not specified, defaults to
31 ``csr_bus.data_width``.
35 wb_bus : :class:`..wishbone.Interface`
36 Wishbone bus provided by the bridge.
38 def __init__(self
, csr_bus
, *, data_width
=None):
39 if not isinstance(csr_bus
, CSRInterface
):
40 raise ValueError("CSR bus must be an instance of CSRInterface, not {!r}"
42 if csr_bus
.data_width
not in (8, 16, 32, 64):
43 raise ValueError("CSR bus data width must be one of 8, 16, 32, 64, not {!r}"
44 .format(csr_bus
.data_width
))
45 if data_width
is None:
46 data_width
= csr_bus
.data_width
48 self
.csr_bus
= csr_bus
49 self
.wb_bus
= WishboneInterface(
50 addr_width
=max(0, csr_bus
.addr_width
- log2_int(data_width
// csr_bus
.data_width
)),
51 data_width
=data_width
,
52 granularity
=csr_bus
.data_width
,
55 # Since granularity of the Wishbone interface matches the data width of the CSR bus,
56 # no width conversion is performed, even if the Wishbone data width is greater.
57 self
.wb_bus
.memory_map
.add_window(self
.csr_bus
.memory_map
)
59 def elaborate(self
, platform
):
60 csr_bus
= self
.csr_bus
65 cycle
= Signal(range(len(wb_bus
.sel
) + 1))
66 m
.d
.comb
+= csr_bus
.addr
.eq(Cat(cycle
[:log2_int(len(wb_bus
.sel
))], wb_bus
.adr
))
68 with m
.If(wb_bus
.cyc
& wb_bus
.stb
):
71 return slice(index
* wb_bus
.granularity
, (index
+ 1) * wb_bus
.granularity
)
73 for index
, sel_index
in enumerate(wb_bus
.sel
):
76 # CSR reads are registered, and we need to re-register them.
77 m
.d
.sync
+= wb_bus
.dat_r
[segment(index
- 1)].eq(csr_bus
.r_data
)
78 m
.d
.comb
+= csr_bus
.r_stb
.eq(sel_index
& ~wb_bus
.we
)
79 m
.d
.comb
+= csr_bus
.w_data
.eq(wb_bus
.dat_w
[segment(index
)])
80 m
.d
.comb
+= csr_bus
.w_stb
.eq(sel_index
& wb_bus
.we
)
81 m
.d
.sync
+= cycle
.eq(index
+ 1)
84 m
.d
.sync
+= wb_bus
.dat_r
[segment(index
)].eq(csr_bus
.r_data
)
85 m
.d
.sync
+= wb_bus
.ack
.eq(1)
86 m
.d
.sync
+= cycle
.eq(0)
89 m
.d
.sync
+= wb_bus
.ack
.eq(0)
90 m
.d
.sync
+= cycle
.eq(0)