Use XDR for RAS#, CAS#, WE#, CLK_EN and ODT
[gram.git] / gram / phy / ecp5ddrphy.py
index e562d65f40a6f7b5dd92f97b24b628f866973f48..9f09bac407b0c432842917c530e5766db87c85ac 100644 (file)
@@ -104,8 +104,8 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         self._bridge = self.bridge(data_width=32, granularity=8, alignment=2)
         self.bus = self._bridge.bus
 
-        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)
@@ -115,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)
@@ -147,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()
@@ -169,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()
@@ -491,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]