Fix write timings
authorJean THOMAS <git0@pub.jeanthomas.me>
Tue, 21 Jul 2020 12:20:01 +0000 (14:20 +0200)
committerJean THOMAS <git0@pub.jeanthomas.me>
Tue, 21 Jul 2020 12:20:01 +0000 (14:20 +0200)
gram/phy/ecp5ddrphy.py

index 89bc2444f741745919bffb503822a639e84b965b..ea5d58c9290e29d3c5b758f4e1ab96712ce42ab7 100644 (file)
@@ -312,15 +312,18 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
             with m.Else():
                 m.d.sync += dm_o_data_muxed.eq(dm_o_data[:4])
 
+            dm_o_data_muxed_d = Signal(4)
+            m.d.sync += dm_o_data_muxed_d.eq(dm_o_data_muxed)
+
             m.submodules += Instance("ODDRX2DQA",
                 i_RST=ResetSignal("dramsync"),
                 i_ECLK=ClockSignal("sync2x"),
                 i_SCLK=ClockSignal("dramsync"),
                 i_DQSW270=dqsw270,
-                i_D0=dm_o_data_muxed[0],
-                i_D1=dm_o_data_muxed[1],
-                i_D2=dm_o_data_muxed[2],
-                i_D3=dm_o_data_muxed[3],
+                i_D2=dm_o_data_muxed[0],
+                i_D3=dm_o_data_muxed[1],
+                i_D0=dm_o_data_muxed_d[2],
+                i_D1=dm_o_data_muxed_d[3],
                 o_Q=self.pads.dm.o[i])
 
             dqs = Signal()
@@ -368,28 +371,32 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
                     dfi.phases[0].wrdata[1*databits+j],
                     dfi.phases[0].wrdata[2*databits+j],
                     dfi.phases[0].wrdata[3*databits+j],
-
                     dfi.phases[1].wrdata[0*databits+j],
                     dfi.phases[1].wrdata[1*databits+j],
                     dfi.phases[1].wrdata[2*databits+j],
                     dfi.phases[1].wrdata[3*databits+j])
                 )
+
                 m.d.sync += dq_o_data_d.eq(dq_o_data)
                 with m.Switch(bl8_chunk):
                     with m.Case(0):
                         m.d.sync += dq_o_data_muxed.eq(dq_o_data[:4])
                     with m.Case(1):
                         m.d.sync += dq_o_data_muxed.eq(dq_o_data_d[4:])
+
+                dq_o_data_muxed_d = Signal.like(dq_o_data_muxed)
+                m.d.sync += dq_o_data_muxed_d.eq(dq_o_data_muxed)
+
                 m.submodules += [
                     Instance("ODDRX2DQA",
                              i_RST=ResetSignal("dramsync"),
                              i_ECLK=ClockSignal("sync2x"),
                              i_SCLK=ClockSignal(),
                              i_DQSW270=dqsw270,
-                             i_D0=dq_o_data_muxed[0],
-                             i_D1=dq_o_data_muxed[1],
-                             i_D2=dq_o_data_muxed[2],
-                             i_D3=dq_o_data_muxed[3],
+                             i_D0=dq_o_data_muxed_d[2],
+                             i_D1=dq_o_data_muxed_d[3],
+                             i_D2=dq_o_data_muxed[0],
+                             i_D3=dq_o_data_muxed[1],
                              o_Q=dq_o
                              ),
                     Instance("DELAYF",
@@ -468,19 +475,19 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         # 2x for DDR, 2x for halfrate) but DDR3 requires a burst of 8 datas (BL8) for best efficiency.
         # Writes are then performed in 2 sys_clk cycles and data needs to be selected for each cycle.
         # FIXME: understand +2
-        wrdata_en = Signal(cwl_sys_latency + 4)
+        wrdata_en = Signal(cwl_sys_latency + 5)
         wrdata_en_last = Signal.like(wrdata_en)
         m.d.comb += wrdata_en.eq(Cat(dfi.phases[self.settings.wrphase].wrdata_en, wrdata_en_last))
         m.d.sync += wrdata_en_last.eq(wrdata_en)
         m.d.comb += dq_oe.eq(wrdata_en[cwl_sys_latency + 1] | wrdata_en[cwl_sys_latency + 2])
         m.d.comb += bl8_chunk.eq(wrdata_en[cwl_sys_latency + 1])
-        m.d.comb += dqs_oe.eq(dq_oe)
+        m.d.comb += dqs_oe.eq(dq_oe | wrdata_en[cwl_sys_latency + 3])
 
         # Write DQS Postamble/Preamble Control Path ------------------------------------------------
         # Generates DQS Preamble 1 cycle before the first write and Postamble 1 cycle after the last
         # write. During writes, DQS tristate is configured as output for at least 4 sys_clk cycles:
         # 1 for Preamble, 2 for the Write and 1 for the Postamble.
         m.d.comb += dqs_preamble.eq(wrdata_en[cwl_sys_latency + 0] & ~wrdata_en[cwl_sys_latency + 1])
-        m.d.comb += dqs_postamble.eq(wrdata_en[cwl_sys_latency + 3] & ~wrdata_en[cwl_sys_latency + 2])
+        m.d.comb += dqs_postamble.eq(wrdata_en[cwl_sys_latency + 4] & ~wrdata_en[cwl_sys_latency + 3])
 
         return m