wishbone.bus: borrow & re-design Arbiter from 'jfng/wishbone-arbiter'
[nmigen-soc.git] / nmigen_soc / wishbone / sram.py
1 from nmigen import *
2 from nmigen.utils import *
3
4 from .bus import Interface
5
6
7 __all__ = ["SRAM"]
8
9
10 class SRAM(Elaboratable):
11 """
12 """
13 def __init__(self, memory, read_only=False, bus=None,
14 granularity=None, features=frozenset()):
15 if not isinstance(memory, Memory):
16 raise TypeError("Memory {!r} is not a Memory"
17 .format(memory))
18 self.memory = memory
19 self.read_only = read_only
20 # Define total address space:
21 # - Base: equals memory.depth
22 # - Has an additional ReadPort: add rdport.depth
23 # - Has an additional WirtePort: add wrport.depth
24 self._memdepth = self.memory.depth * 2
25 if not read_only:
26 self._memdepth += self.memory.depth
27 if bus is None:
28 bus = Interface(addr_width=max(0, log2_int(self._memdepth, need_pow2=False)),
29 data_width=self.memory.width,
30 granularity=granularity,
31 features=features,
32 alignment=0,
33 name=None)
34 self.bus = bus
35 self.granularity = bus.granularity
36
37 def elaborate(self, platform):
38 m = Module()
39
40 if self.memory.width > len(self.bus.dat_r):
41 raise NotImplementedError
42
43 # read
44 m.submodules.rdport = rdport = self.memory.read_port()
45 m.d.comb += [
46 rdport.addr.eq(self.bus.adr[:len(rdport.addr)]),
47 self.bus.dat_r.eq(rdport.data)
48 ]
49
50 # write
51 if not self.read_only:
52 m.submodules.wrport = wrport = self.memory.write_port(granularity=self.granularity)
53 m.d.comb += [
54 wrport.addr.eq(self.bus.adr[:len(rdport.addr)]),
55 wrport.data.eq(self.bus.dat_w)
56 ]
57 for i in range(4):
58 m.d.comb += wrport.en[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i])
59
60 # generate ack
61 m.d.sync += self.bus.ack.eq(0)
62 with m.If(self.bus.cyc & self.bus.stb & ~self.bus.ack):
63 m.d.sync += self.bus.ack.eq(1)
64
65 return m