2 from nmigen
.utils
import *
4 from .bus
import Interface
10 class SRAM(Elaboratable
):
11 """SRAM module carrying a volatile memory block (implemented with :class:`Memory`)
12 that can be read and write (or only read if the SRAM is read-only) through a Wishbone bus.
14 If no Wishbone bus is specified during initialisation, this creates one whose address width
15 is just enough to fit the whole memory (i.e. equals to the log2(memory depth) rounded up), and
16 whose data width is equal to the memory width.
20 memory : :class:`Memory`
21 The memory to be accessed via the Wishbone bus.
23 Whether or not the memory is read-only. Defaults to False.
24 bus : :class:`Interface` or None
25 The Wishbone bus interface providing access to the read/write ports of the memory.
26 Optional and defaults to None, which lets this module to instantiate one as described
27 above, having the granularity, features and alignment as specified by their
28 corresponding parameters.
29 granularity : int or None
30 If the Wishbone bus is not sepcified, this is the granularity of the Wishbone bus.
31 Optional. See :class:`Interface`.
33 If the Wishbone bus is not sepcified, this is the optional signal set for the Wishbone bus.
34 See :class:`Interface`.
38 memory : :class:`Memory`
39 The memory to be accessed via the Wishbone bus.
40 bus : :class:`Interface`
41 The Wishbone bus interface providing access to the read/write ports of the memory.
43 def __init__(self
, memory
, read_only
=False, bus
=None,
44 granularity
=None, features
=frozenset()):
45 if not isinstance(memory
, Memory
):
46 raise TypeError("Memory {!r} is not a Memory"
49 self
.read_only
= read_only
51 bus
= Interface(addr_width
=log2_int(self
.memory
.depth
, need_pow2
=False),
52 data_width
=self
.memory
.width
,
53 granularity
=granularity
,
58 self
.granularity
= bus
.granularity
60 def elaborate(self
, platform
):
63 if self
.memory
.width
> len(self
.bus
.dat_r
):
64 raise NotImplementedError
67 m
.submodules
.rdport
= rdport
= self
.memory
.read_port()
69 rdport
.addr
.eq(self
.bus
.adr
[:len(rdport
.addr
)]),
70 self
.bus
.dat_r
.eq(rdport
.data
)
74 if not self
.read_only
:
75 m
.submodules
.wrport
= wrport
= self
.memory
.write_port(granularity
=self
.granularity
)
77 wrport
.addr
.eq(self
.bus
.adr
[:len(rdport
.addr
)]),
78 wrport
.data
.eq(self
.bus
.dat_w
)
81 m
.d
.comb
+= wrport
.en
[i
].eq(self
.bus
.cyc
& self
.bus
.stb
&
82 self
.bus
.we
& self
.bus
.sel
[i
])
85 m
.d
.sync
+= self
.bus
.ack
.eq(0)
86 with m
.If(self
.bus
.cyc
& self
.bus
.stb
& ~self
.bus
.ack
):
87 m
.d
.sync
+= self
.bus
.ack
.eq(1)