2 from nmigen
.utils
import log2_int
4 from nmigen_soc
import wishbone
5 from nmigen_soc
.memory
import MemoryMap
6 from nmigen_soc
.periph
import ConstantMap
8 from . import Peripheral
11 __all__
= ["SRAMPeripheral"]
14 class SRAMPeripheral(Peripheral
, Elaboratable
):
15 """SRAM storage peripheral.
30 bus : :class:`nmigen_soc.wishbone.Interface`
31 Wishbone bus interface.
33 # TODO raise bus.err if read-only and a bus write is attempted.
34 def __init__(self
, *, size
, data_width
=32, granularity
=8, writable
=True):
37 if not isinstance(size
, int) or size
<= 0 or size
& size
-1:
38 raise ValueError("Size must be an integer power of two, not {!r}"
40 if size
< data_width
// granularity
:
41 raise ValueError("Size {} cannot be lesser than the data width/granularity ratio "
43 .format(size
, data_width
// granularity
, data_width
, granularity
))
45 self
._mem
= Memory(depth
=(size
* granularity
) // data_width
, width
=data_width
)
47 self
.bus
= wishbone
.Interface(addr_width
=log2_int(self
._mem
.depth
),
48 data_width
=self
._mem
.width
, granularity
=granularity
,
49 features
={"cti", "bte"})
51 map = MemoryMap(addr_width
=log2_int(size
), data_width
=granularity
, name
=self
.name
)
52 map.add_resource(self
._mem
, name
="mem", size
=size
)
53 self
.bus
.memory_map
= map
56 self
.granularity
= granularity
57 self
.writable
= writable
68 def constant_map(self
):
73 def elaborate(self
, platform
):
76 incr
= Signal
.like(self
.bus
.adr
)
78 with m
.Switch(self
.bus
.bte
):
79 with m
.Case(wishbone
.BurstTypeExt
.LINEAR
):
80 m
.d
.comb
+= incr
.eq(self
.bus
.adr
+ 1)
81 with m
.Case(wishbone
.BurstTypeExt
.WRAP_4
):
82 m
.d
.comb
+= incr
[:2].eq(self
.bus
.adr
[:2] + 1)
83 m
.d
.comb
+= incr
[2:].eq(self
.bus
.adr
[2:])
84 with m
.Case(wishbone
.BurstTypeExt
.WRAP_8
):
85 m
.d
.comb
+= incr
[:3].eq(self
.bus
.adr
[:3] + 1)
86 m
.d
.comb
+= incr
[3:].eq(self
.bus
.adr
[3:])
87 with m
.Case(wishbone
.BurstTypeExt
.WRAP_16
):
88 m
.d
.comb
+= incr
[:4].eq(self
.bus
.adr
[:4] + 1)
89 m
.d
.comb
+= incr
[4:].eq(self
.bus
.adr
[4:])
91 m
.submodules
.mem_rp
= mem_rp
= self
._mem
.read_port()
92 m
.d
.comb
+= self
.bus
.dat_r
.eq(mem_rp
.data
)
94 with m
.If(self
.bus
.ack
):
95 m
.d
.sync
+= self
.bus
.ack
.eq(0)
97 with m
.If(self
.bus
.cyc
& self
.bus
.stb
):
98 m
.d
.sync
+= self
.bus
.ack
.eq(1)
99 with m
.If((self
.bus
.cti
== wishbone
.CycleType
.INCR_BURST
) & self
.bus
.ack
):
100 m
.d
.comb
+= mem_rp
.addr
.eq(incr
)
102 m
.d
.comb
+= mem_rp
.addr
.eq(self
.bus
.adr
)
105 m
.submodules
.mem_wp
= mem_wp
= self
._mem
.write_port(granularity
=self
.granularity
)
106 m
.d
.comb
+= mem_wp
.addr
.eq(mem_rp
.addr
)
107 m
.d
.comb
+= mem_wp
.data
.eq(self
.bus
.dat_w
)
108 with m
.If(self
.bus
.cyc
& self
.bus
.stb
& self
.bus
.we
):
109 m
.d
.comb
+= mem_wp
.en
.eq(self
.bus
.sel
)