soc/cores: add initial simple hyperram core
authorAntti Lukats <Antti.Lukats@googlemail.com>
Fri, 16 Aug 2019 07:46:15 +0000 (09:46 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 16 Aug 2019 07:48:17 +0000 (09:48 +0200)
litex/soc/cores/hyper_memory.py [new file with mode: 0644]

diff --git a/litex/soc/cores/hyper_memory.py b/litex/soc/cores/hyper_memory.py
new file mode 100644 (file)
index 0000000..18b1339
--- /dev/null
@@ -0,0 +1,125 @@
+# This file is Copyright (c) 2019 Antti Lukats <antti.lukats@gmail.com>
+# This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
+
+# License: BSD
+
+#
+#
+#
+
+from migen import *
+from migen.genlib.misc import timeline
+
+from litex.gen import *
+
+from litex.soc.interconnect import wishbone
+from litex.soc.interconnect.csr import *
+
+
+class HyperMemporyCommon(Module):
+    def __init__(self, pads):
+        self.pads = pads
+
+class HyperRAM(HyperMemporyCommon):
+    def __init__(self, pads):
+        """
+        HyperRAM simple core for LiteX
+        This core should always just work on any FPGA platorm it is fully vendor neutral
+        No configuration, no software setup, ready after poweron, fixed latency
+
+        """
+        HyperMemporyCommon.__init__(self, pads)
+
+        if hasattr(pads, "rst_n"):
+            self.comb += pads.rst_n.eq(1)
+        if hasattr(pads, "cs1_n"):
+            self.comb += pads.cs1_n.eq(1)
+
+        # Tristate pads
+        dq = TSTriple(8)
+        self.specials.dq = dq.get_tristate(pads.dq)
+        rwds = TSTriple(1)
+        self.specials.rwds = rwds.get_tristate(pads.rwds)
+
+        # Wishbone
+        self.bus = bus = wishbone.Interface()
+        sr = Signal(48)
+
+        dq_oe = Signal(reset=0)
+        rwds_oe = Signal(reset=0)
+        cs_int = Signal(reset=1)
+
+        self.comb += [
+            bus.dat_r.eq(sr),
+            dq.oe.eq(dq_oe),
+            dq.o.eq(sr[-8:]),
+            rwds.oe.eq(rwds_oe),
+            pads.cs0_n.eq(cs_int)
+        ]
+
+        # we generate complementaty clk out for emulated differential output
+        clk_p = Signal(1)
+        clk_n = Signal(1)
+
+        self.comb += pads.clk.eq(clk_p)
+        # if negative is defined drive complementary clock out
+        if hasattr(pads, "clk_n"):
+            self.comb += pads.clk_n.eq(clk_n)
+        # 1 sys clock delay needed to adjust input timings?
+        dqi = Signal(8)
+        self.sync += [
+                dqi.eq(dq.i)
+        ]
+        # hyper RAM clock generator and 48 bit byte shifter
+        i = Signal(max=4)
+        self.sync += [
+            If(i == 0,
+                sr.eq(Cat(dqi, sr[:-8])),
+            ),
+            If(i == 1,
+                clk_p.eq(~cs_int), # 1
+                clk_n.eq(cs_int)   # 0
+            ),
+            If(i == 2,
+                sr.eq(Cat(dqi, sr[:-8]))
+            ),
+            If(i == 3,
+                i.eq(0),
+                clk_p.eq(0),      # 1
+                clk_n.eq(1)       # 0
+            ).Else(
+                i.eq(i + 1)
+            )
+        ]
+        # signals to use CA or data to write
+        CA = Signal(48)
+        # combine bits to create CA bytes
+        self.comb += [
+            CA[47].eq(~self.bus.we),
+            CA[45].eq(1),
+            CA[16:35].eq(self.bus.adr[2:21]),
+            CA[1:3].eq(self.bus.adr[0:2]),
+            CA[0].eq(0),
+        ]
+        z = Replicate(0, 16)
+        seq = [
+            (3,        []),
+            (12,       [cs_int.eq(0), dq_oe.eq(1), sr.eq(CA)]), # 6 clock edges for command transmit
+            (44,       [dq_oe.eq(0)]),                          # 6+6 latency default
+            (2,        [dq_oe.eq(self.bus.we), rwds_oe.eq(self.bus.we), rwds.o.eq(~bus.sel[0]), sr.eq(Cat(z, self.bus.dat_w))]), # 4 edges to write data
+            (2,        [rwds.o.eq(~bus.sel[1])]), # 4 edges to write data
+            (2,        [rwds.o.eq(~bus.sel[2])]), # 4 edges to write data
+            (2,        [rwds.o.eq(~bus.sel[3])]), # 4 edges to write data
+            (2,        [cs_int.eq(1), rwds_oe.eq(0), dq_oe.eq(0)]),
+            (1,        [bus.ack.eq(1)]), # is 1 also OK?
+            (1,        [bus.ack.eq(0)]), #
+            (0,        []),
+        ]
+
+        t, tseq = 0, []
+        for dt, a in seq:
+            tseq.append((t, a))
+            t += dt
+
+        self.sync += timeline(bus.cyc & bus.stb & (i == 1), tseq)
+