Use XDR for RAS#, CAS#, WE#, CLK_EN and ODT
[gram.git] / gram / phy / ecp5ddrphy.py
index 408a69eca2bee91435d536313bc67f688fbd14b2..9f09bac407b0c432842917c530e5766db87c85ac 100644 (file)
@@ -82,7 +82,6 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
     def __init__(self, pads, sys_clk_freq=100e6):
         super().__init__(name="phy")
 
-        #self.pads = PHYPadsCombiner(pads)
         self.pads = pads
         self._sys_clk_freq = sys_clk_freq
 
@@ -102,14 +101,11 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         self._burstdet_clr = bank.csr(1, "rw")
         self._burstdet_seen = bank.csr(databits//8, "r")
 
-        self._zero_ev = self.event(mode="rise")
-
         self._bridge = self.bridge(data_width=32, granularity=8, alignment=2)
         self.bus = self._bridge.bus
-        self.irq = self._bridge.irq
 
-        addressbits = len(self.pads.a.o)
-        bankbits = len(self.pads.ba.o)
+        addressbits = len(self.pads.a.o0)
+        bankbits = len(self.pads.ba.o0)
         nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n.o)
         databits = len(self.pads.dq.io)
         self.dfi = Interface(addressbits, bankbits, nranks, 4*databits, 4)
@@ -119,8 +115,6 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         nphases = 2
         databits = len(self.pads.dq.io)
         nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n.o)
-        addressbits = len(self.pads.a.o)
-        bankbits = len(self.pads.ba.o)
         cl, cwl = get_cl_cw("DDR3", tck)
         cl_sys_latency = get_sys_latency(nphases, cl)
         cwl_sys_latency = get_sys_latency(nphases, cwl)
@@ -151,9 +145,6 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         tck = 2/(2*2*self._sys_clk_freq)
         nphases = 2
         databits = len(self.pads.dq.io)
-        nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n.o)
-        addressbits = len(self.pads.a.o)
-        bankbits = len(self.pads.ba.o)
 
         # Init -------------------------------------------------------------------------------------
         m.submodules.init = init = ECP5DDRPHYInit()
@@ -173,59 +164,57 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         rddata_en = Signal(self.settings.read_latency)
 
         # Clock --------------------------------------------------------------------------------
-        for i in range(len(self.pads.clk.o)):
-            sd_clk_se = Signal()
-            m.submodules += Instance("ODDRX2F",
-                                     i_RST=ResetSignal("dramsync"),
-                                     i_ECLK=ClockSignal("sync2x"),
-                                     i_SCLK=ClockSignal(),
-                                     i_D0=0,
-                                     i_D1=1,
-                                     i_D2=0,
-                                     i_D3=1,
-                                     o_Q=self.pads.clk.o[i]
-                                     )
+        m.d.comb += [
+            self.pads.clk.o_clk.eq(ClockSignal("dramsync")),
+            self.pads.clk.o_fclk.eq(ClockSignal("sync2x")),
+        ]
+        for i in range(len(self.pads.clk.o0)):
+            m.d.comb += [
+                self.pads.clk.o0[i].eq(0),
+                self.pads.clk.o1[i].eq(1),
+                self.pads.clk.o2[i].eq(0),
+                self.pads.clk.o3[i].eq(1),
+            ]
 
         # Addresses and Commands ---------------------------------------------------------------
-        for i in range(addressbits):
-            m.submodules += Instance("ODDRX2F",
-                                     i_RST=ResetSignal("dramsync"),
-                                     i_ECLK=ClockSignal("sync2x"),
-                                     i_SCLK=ClockSignal(),
-                                     i_D0=dfi.phases[0].address[i],
-                                     i_D1=dfi.phases[0].address[i],
-                                     i_D2=dfi.phases[1].address[i],
-                                     i_D3=dfi.phases[1].address[i],
-                                     o_Q=self.pads.a.o[i]
-                                     )
-        for i in range(bankbits):
-            m.submodules += Instance("ODDRX2F",
-                                     i_RST=ResetSignal("dramsync"),
-                                     i_ECLK=ClockSignal("sync2x"),
-                                     i_SCLK=ClockSignal(),
-                                     i_D0=dfi.phases[0].bank[i],
-                                     i_D1=dfi.phases[0].bank[i],
-                                     i_D2=dfi.phases[1].bank[i],
-                                     i_D3=dfi.phases[1].bank[i],
-                                     o_Q=self.pads.ba.o[i]
-                                     )
+        m.d.comb += [
+            self.pads.a.o_clk.eq(ClockSignal("dramsync")),
+            self.pads.a.o_fclk.eq(ClockSignal("sync2x")),
+            self.pads.ba.o_clk.eq(ClockSignal("dramsync")),
+            self.pads.ba.o_fclk.eq(ClockSignal("sync2x")),
+        ]
+        for i in range(len(self.pads.a.o0)):
+            m.d.comb += [
+                self.pads.a.o0[i].eq(dfi.phases[0].address[i]),
+                self.pads.a.o1[i].eq(dfi.phases[0].address[i]),
+                self.pads.a.o2[i].eq(dfi.phases[1].address[i]),
+                self.pads.a.o3[i].eq(dfi.phases[1].address[i]),
+            ]
+        for i in range(len(self.pads.ba.o0)):
+            m.d.comb += [
+                self.pads.ba.o0[i].eq(dfi.phases[0].bank[i]),
+                self.pads.ba.o1[i].eq(dfi.phases[0].bank[i]),
+                self.pads.ba.o2[i].eq(dfi.phases[1].bank[i]),
+                self.pads.ba.o3[i].eq(dfi.phases[1].bank[i]),
+            ]
+
         controls = ["ras_n", "cas_n", "we_n", "clk_en", "odt"]
         if hasattr(self.pads, "reset_n"):
             controls.append("reset_n")
         if hasattr(self.pads, "cs_n"):
             controls.append("cs_n")
         for name in controls:
-            for i in range(len(getattr(self.pads, name))):
-                m.submodules += Instance("ODDRX2F",
-                                         i_RST=ResetSignal("dramsync"),
-                                         i_ECLK=ClockSignal("sync2x"),
-                                         i_SCLK=ClockSignal(),
-                                         i_D0=getattr(dfi.phases[0], name)[i],
-                                         i_D1=getattr(dfi.phases[0], name)[i],
-                                         i_D2=getattr(dfi.phases[1], name)[i],
-                                         i_D3=getattr(dfi.phases[1], name)[i],
-                                         o_Q=getattr(self.pads, name).o[i]
-                                         )
+            m.d.comb += [
+                getattr(self.pads, name).o_clk.eq(ClockSignal("dramsync")),
+                getattr(self.pads, name).o_fclk.eq(ClockSignal("sync2x")),
+            ]
+            for i in range(len(getattr(self.pads, name).o0)):
+                m.d.comb += [
+                    getattr(self.pads, name).o0[i].eq(getattr(dfi.phases[0], name)[i]),
+                    getattr(self.pads, name).o1[i].eq(getattr(dfi.phases[0], name)[i]),
+                    getattr(self.pads, name).o2[i].eq(getattr(dfi.phases[1], name)[i]),
+                    getattr(self.pads, name).o3[i].eq(getattr(dfi.phases[1], name)[i]),
+                ]
 
         # DQ ---------------------------------------------------------------------------------------
         dq_oe = Signal()
@@ -258,7 +247,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
             with m.Switch(dqs_bitslip):
                 for j, b in enumerate(range(-2, 2)):
                     with m.Case(j):
-                        m.d.sync += dqs_read.eq(rddata_en[cl_sys_latency + b:cl_sys_latency + b + 2] != 0)
+                        m.d.sync += dqs_read.eq(1)
 
             m.submodules += Instance("DQSBUFM",
                                      p_DQS_LI_DEL_ADJ="MINUS",
@@ -344,7 +333,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
             m.submodules += Instance("ODDRX2DQA",
                                      i_RST=ResetSignal("dramsync"),
                                      i_ECLK=ClockSignal("sync2x"),
-                                     i_SCLK=ClockSignal("sync"),
+                                     i_SCLK=ClockSignal("dramsync"),
                                      i_DQSW270=dqsw270,
                                      i_D0=dm_o_data_muxed[0],
                                      i_D1=dm_o_data_muxed[1],
@@ -454,7 +443,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
                 ]
                 m.d.sync += dq_i_data[:4].eq(dq_i_data[4:])
                 m.d.sync += dq_i_data[4:].eq(_dq_i_data)
-                m.d.comb += [
+                m.d.sync += [
                     dfi.phases[0].rddata[0*databits+j].eq(dq_i_data[0]),
                     dfi.phases[0].rddata[1*databits+j].eq(dq_i_data[1]),
                     dfi.phases[0].rddata[2*databits+j].eq(dq_i_data[2]),
@@ -495,8 +484,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         # The read data valid is asserted for 1 sys_clk cycle when the data is available on the DFI
         # interface, the latency is the sum of the ODDRX2DQA, CAS, IDDRX2DQA latencies.
         rddata_en_last = Signal.like(rddata_en)
-        m.d.comb += rddata_en.eq(
-            Cat(dfi.phases[self.settings.rdphase].rddata_en, rddata_en_last))
+        m.d.comb += rddata_en.eq(Cat(dfi.phases[self.settings.rdphase].rddata_en, rddata_en_last))
         m.d.sync += rddata_en_last.eq(rddata_en)
         m.d.sync += [phase.rddata_valid.eq(rddata_en[-1])
                      for phase in dfi.phases]