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.
39 def __init__(self
, csr_bus
, *, data_width
=None):
40 if not isinstance(csr_bus
, CSRInterface
):
41 raise ValueError("CSR bus must be an instance of CSRInterface, "
42 "not {!r}" .format(csr_bus
))
43 if csr_bus
.data_width
not in (8, 16, 32, 64):
44 raise ValueError("CSR bus data width must be one of 8, 16, 32, 64, "
45 "not {!r}" .format(csr_bus
.data_width
))
46 if data_width
is None:
47 data_width
= csr_bus
.data_width
49 self
.csr_bus
= csr_bus
50 self
.wb_bus
= WishboneInterface(
57 data_width
=data_width
,
58 granularity
=csr_bus
.data_width
,
61 # Since granularity of the Wishbone interface matches the data
62 # width of the CSR bus, no width conversion is performed, even
63 # if the Wishbone data width is greater.
64 self
.wb_bus
.memory_map
.add_window(self
.csr_bus
.memory_map
)
66 def elaborate(self
, platform
):
67 csr_bus
= self
.csr_bus
72 cycle
= Signal(range(len(wb_bus
.sel
) + 1))
73 m
.d
.comb
+= csr_bus
.addr
.eq(
74 Cat(cycle
[:log2_int(len(wb_bus
.sel
))], wb_bus
.adr
))
76 with m
.If(wb_bus
.cyc
& wb_bus
.stb
):
79 return slice(index
* wb_bus
.granularity
,
80 (index
+ 1) * wb_bus
.granularity
)
82 for index
, sel_index
in enumerate(wb_bus
.sel
):
85 # CSR reads are registered, and we need to
87 m
.d
.sync
+= wb_bus
.dat_r
[segment(
88 index
- 1)].eq(csr_bus
.r_data
)
89 m
.d
.comb
+= csr_bus
.r_stb
.eq(sel_index
& ~wb_bus
.we
)
90 m
.d
.comb
+= csr_bus
.w_data
.eq(
91 wb_bus
.dat_w
[segment(index
)])
92 m
.d
.comb
+= csr_bus
.w_stb
.eq(sel_index
& wb_bus
.we
)
93 m
.d
.sync
+= cycle
.eq(index
+ 1)
96 m
.d
.sync
+= wb_bus
.dat_r
[segment(index
)].eq(csr_bus
.r_data
)
97 m
.d
.sync
+= wb_bus
.ack
.eq(1)
98 m
.d
.sync
+= cycle
.eq(0)
101 m
.d
.sync
+= wb_bus
.ack
.eq(0)
102 m
.d
.sync
+= cycle
.eq(0)