add Wishbone-wrapped SPBlock_512W64B8W
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 20 Feb 2021 14:30:07 +0000 (14:30 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 20 Feb 2021 14:30:07 +0000 (14:30 +0000)
src/soc/bus/SPBlock512W64B8W.py [new file with mode: 0644]

diff --git a/src/soc/bus/SPBlock512W64B8W.py b/src/soc/bus/SPBlock512W64B8W.py
new file mode 100644 (file)
index 0000000..aa7fe20
--- /dev/null
@@ -0,0 +1,80 @@
+from nmigen import Elaboratable, Cat, Module, Signal, ClockSignal, Instance
+from nmigen.utils import log2_int
+
+from nmigen_soc.wishbone.bus import Interface
+from nmigen.cli import rtlil
+
+__all__ = ["SPBlock512W64B8W"]
+
+
+class SPBlock512W64B8W(Elaboratable):
+    """SRAM module carrying a volatile 4k memory block (implemented with
+    Instance SPBlock512W64B8W).  512 rows, 64-bit, QTY 8 write-enable lines
+    """
+
+    def __init__(self, bus=None, features=None):
+        if features is None:
+            features = frozenset()
+        if bus is None:
+            bus = Interface(addr_width=9,  # 512 lines of
+                            data_width=64, # 64 bit
+                            granularity=8, # at 8-bit granularity
+                            features=features,
+                            alignment=0,
+                            name=None)
+        self.bus = bus
+        self.granularity = bus.granularity
+
+        n_wrport = 8
+        n_bussel = self.bus.sel.width
+        assert n_wrport == n_bussel, "bus enable count %d " \
+                "must match memory wen count %d" % (n_wrport, n_bussel)
+
+        assert len(self.bus.dat_r) == 64, "bus width must be 64"
+
+    def elaborate(self, platform):
+        m = Module()
+
+        # 4k SRAM instance
+        a = Signal(9)
+        we = Signal()
+        q = Signal(64) # output
+        d = Signal(64) # input
+
+        sram = Instance("SPBlock_512W64B8W", i_a=a, o_q=q, i_d=d,
+                                             i_we=we, i_clk=ClockSignal())
+        m.submodules += sram
+
+        wb_active = Signal()
+        m.d.comb += wb_active.eq(self.bus.cyc & self.bus.stb)
+        with m.If(wb_active):
+            # address
+            m.d.comb += a.eq(self.bus.adr)
+
+            # read 
+            m.d.comb += self.bus.dat_r.eq(q)
+
+            # write
+            m.d.comb += d.eq(self.bus.dat_w)
+            with m.If(self.bus.we):
+                m.d.comb += we.eq(self.bus.sel)
+
+        # generate ack (no "pipeline" mode here)
+        m.d.sync += self.bus.ack.eq(0)
+        with m.If(self.bus.cyc & self.bus.stb):
+            m.d.sync += self.bus.ack.eq(1)
+
+        return m
+
+
+def create_ilang(dut, ports, test_name):
+    vl = rtlil.convert(dut, name=test_name, ports=ports)
+    with open("%s.il" % test_name, "w") as f:
+        f.write(vl)
+
+if __name__ == "__main__":
+    alu = SPBlock512W64B8W()
+    create_ilang(alu, [alu.bus.cyc, alu.bus.stb, alu.bus.ack,
+                       alu.bus.dat_r, alu.bus.dat_w, alu.bus.adr,
+                       alu.bus.we, alu.bus.sel], "SPBlock512W64B8W")
+