Fix peripheral addresses, improve memory testing
[gram.git] / gram / phy / ecp5ddrphy.py
index 89bc2444f741745919bffb503822a639e84b965b..394e6522ea9e92751058d6cb0e309b09b8296669 100644 (file)
@@ -40,13 +40,12 @@ class ECP5DDRPHYInit(Elaboratable):
         _lock = Signal()
         delay = Signal()
         m.submodules += Instance("DDRDLLA",
-                                 i_CLK=ClockSignal("sync2x"),
-                                 i_RST=ResetSignal("init"),
-                                 i_UDDCNTLN=~update,
-                                 i_FREEZE=freeze,
-                                 o_DDRDEL=delay,
-                                 o_LOCK=_lock
-                                 )
+            i_CLK=ClockSignal("sync2x"),
+            i_RST=ResetSignal("init"),
+            i_UDDCNTLN=~update,
+            i_FREEZE=freeze,
+            o_DDRDEL=delay,
+            o_LOCK=_lock)
         lock = Signal()
         lock_d = Signal()
         m.submodules += FFSynchronizer(_lock, lock, o_domain="init")
@@ -91,15 +90,11 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         # CSR
         bank = self.csr_bank()
 
-        self._dly_sel = bank.csr(databits//8, "rw")
+        self.burstdet = bank.csr(databits//8, "rw")
 
-        self._rdly_dq_rst = bank.csr(1, "rw")
-        self._rdly_dq_inc = bank.csr(1, "rw")
-        self._rdly_dq_bitslip_rst = bank.csr(1, "rw")
-        self._rdly_dq_bitslip = bank.csr(1, "rw")
-
-        self._burstdet_clr = bank.csr(1, "rw")
-        self._burstdet_seen = bank.csr(databits//8, "r")
+        self.rdly = []
+        self.rdly += [bank.csr(3, "rw", name="rdly_p0")]
+        self.rdly += [bank.csr(3, "rw", name="rdly_p1")]
 
         self._bridge = self.bridge(data_width=32, granularity=8, alignment=2)
         self.bus = self._bridge.bus
@@ -111,7 +106,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         self.dfi = Interface(addressbits, bankbits, nranks, 4*databits, 4)
 
         # PHY settings -----------------------------------------------------------------------------
-        tck = 2/(2*2*self._sys_clk_freq)
+        tck = 1/(2*self._sys_clk_freq)
         nphases = 2
         databits = len(self.pads.dq.io)
         nranks = 1 if not hasattr(self.pads, "cs") else len(self.pads.cs.o0)
@@ -142,10 +137,17 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
 
         m.submodules.bridge = self._bridge
 
-        tck = 2/(2*2*self._sys_clk_freq)
+        tck = 1/(2*self._sys_clk_freq)
         nphases = 2
         databits = len(self.pads.dq.io)
 
+        burstdet_reg = Signal(databits//8)
+        m.d.comb += self.burstdet.r_data.eq(burstdet_reg)
+
+        # Burstdet clear
+        with m.If(self.burstdet.w_stb):
+            m.d.sync += burstdet_reg.eq(0)
+
         # Init -------------------------------------------------------------------------------------
         m.submodules.init = init = ECP5DDRPHYInit()
 
@@ -197,6 +199,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
                 self.pads.ba.o3[i].eq(dfi.phases[1].bank[i]),
             ]
 
+        # Control pins
         controls = ["ras", "cas", "we", "clk_en", "odt"]
         if hasattr(self.pads, "reset"):
             controls.append("reset")
@@ -217,6 +220,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
 
         # DQ ---------------------------------------------------------------------------------------
         dq_oe = Signal()
+        dqs_re = Signal()
         dqs_oe = Signal()
         dqs_postamble = Signal()
         dqs_preamble = Signal()
@@ -228,67 +232,63 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
             dqsw = Signal()
             rdpntr = Signal(3)
             wrpntr = Signal(3)
-            rdly = Signal(7)
             burstdet = Signal()
 
             m.submodules += Instance("DQSBUFM",
-                                     p_DQS_LI_DEL_ADJ="MINUS",
-                                     p_DQS_LI_DEL_VAL=1,
-                                     p_DQS_LO_DEL_ADJ="MINUS",
-                                     p_DQS_LO_DEL_VAL=4,
-
-                                     # Delay
-                                     i_DYNDELAY0=0,
-                                     i_DYNDELAY1=0,
-                                     i_DYNDELAY2=0,
-                                     i_DYNDELAY3=0,
-                                     i_DYNDELAY4=0,
-                                     i_DYNDELAY5=0,
-                                     i_DYNDELAY6=0,
-                                     i_DYNDELAY7=0,
-
-                                     # Clocks / Reset
-                                     i_SCLK=ClockSignal("sync"),
-                                     i_ECLK=ClockSignal("sync2x"),
-                                     i_RST=ResetSignal("dramsync"),
-                                     i_DDRDEL=init.delay,
-                                     i_PAUSE=init.pause | self._dly_sel.w_data[i],
-
-                                     # Control
-                                     # Assert LOADNs to use DDRDEL control
-                                     i_RDLOADN=0,
-                                     i_RDMOVE=0,
-                                     i_RDDIRECTION=1,
-                                     i_WRLOADN=0,
-                                     i_WRMOVE=0,
-                                     i_WRDIRECTION=1,
-
-                                     # Reads (generate shifted DQS clock for reads)
-                                     i_READ0=1,
-                                     i_READ1=1,
-                                     i_READCLKSEL0=rdly[0],
-                                     i_READCLKSEL1=rdly[1],
-                                     i_READCLKSEL2=rdly[2],
-                                     i_DQSI=dqs_i,
-                                     o_DQSR90=dqsr90,
-                                     o_RDPNTR0=rdpntr[0],
-                                     o_RDPNTR1=rdpntr[1],
-                                     o_RDPNTR2=rdpntr[2],
-                                     o_WRPNTR0=wrpntr[0],
-                                     o_WRPNTR1=wrpntr[1],
-                                     o_WRPNTR2=wrpntr[2],
-                                     o_DATAVALID=self.datavalid[i],
-                                     o_BURSTDET=burstdet,
-
-                                     # Writes (generate shifted ECLK clock for writes)
-                                     o_DQSW270=dqsw270,
-                                     o_DQSW=dqsw)
-            burstdet_d = Signal()
-            m.d.sync += burstdet_d.eq(burstdet)
-            with m.If(self._burstdet_clr.w_stb):
-                m.d.sync += self._burstdet_seen.r_data[i].eq(0)
-            with m.If(burstdet & ~burstdet_d):
-                m.d.sync += self._burstdet_seen.r_data[i].eq(1)
+                p_DQS_LI_DEL_ADJ="MINUS",
+                p_DQS_LI_DEL_VAL=1,
+                p_DQS_LO_DEL_ADJ="MINUS",
+                p_DQS_LO_DEL_VAL=4,
+
+                # Delay
+                i_DYNDELAY0=0,
+                i_DYNDELAY1=0,
+                i_DYNDELAY2=0,
+                i_DYNDELAY3=0,
+                i_DYNDELAY4=0,
+                i_DYNDELAY5=0,
+                i_DYNDELAY6=0,
+                i_DYNDELAY7=0,
+
+                # Clocks / Reset
+                i_SCLK=ClockSignal("sync"),
+                i_ECLK=ClockSignal("sync2x"),
+                i_RST=ResetSignal("dramsync"),
+                i_DDRDEL=init.delay,
+                i_PAUSE=init.pause | self.rdly[i].w_stb,
+
+                # Control
+                # Assert LOADNs to use DDRDEL control
+                i_RDLOADN=0,
+                i_RDMOVE=0,
+                i_RDDIRECTION=1,
+                i_WRLOADN=0,
+                i_WRMOVE=0,
+                i_WRDIRECTION=1,
+
+                # Reads (generate shifted DQS clock for reads)
+                i_READ0=dqs_re,
+                i_READ1=dqs_re,
+                i_READCLKSEL0=self.rdly[i].w_data[0],
+                i_READCLKSEL1=self.rdly[i].w_data[1],
+                i_READCLKSEL2=self.rdly[i].w_data[2],
+                i_DQSI=dqs_i,
+                o_DQSR90=dqsr90,
+                o_RDPNTR0=rdpntr[0],
+                o_RDPNTR1=rdpntr[1],
+                o_RDPNTR2=rdpntr[2],
+                o_WRPNTR0=wrpntr[0],
+                o_WRPNTR1=wrpntr[1],
+                o_WRPNTR2=wrpntr[2],
+                o_DATAVALID=self.datavalid[i],
+                o_BURSTDET=burstdet,
+
+                # Writes (generate shifted ECLK clock for writes)
+                o_DQSW270=dqsw270,
+                o_DQSW=dqsw)
+
+            with m.If(burstdet):
+                m.d.sync += burstdet_reg[i].eq(1)
 
             # DQS and DM ---------------------------------------------------------------------------
             dm_o_data = Signal(8)
@@ -327,31 +327,28 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
             dqs_oe_n = Signal()
             m.submodules += [
                 Instance("ODDRX2DQSB",
-                         i_RST=ResetSignal("dramsync"),
-                         i_ECLK=ClockSignal("sync2x"),
-                         i_SCLK=ClockSignal(),
-                         i_DQSW=dqsw,
-                         i_D0=0,
-                         i_D1=1,
-                         i_D2=0,
-                         i_D3=1,
-                         o_Q=dqs
-                         ),
+                    i_RST=ResetSignal("dramsync"),
+                    i_ECLK=ClockSignal("sync2x"),
+                    i_SCLK=ClockSignal(),
+                    i_DQSW=dqsw,
+                    i_D0=0,
+                    i_D1=1,
+                    i_D2=0,
+                    i_D3=1,
+                    o_Q=dqs),
                 Instance("TSHX2DQSA",
-                         i_RST=ResetSignal("dramsync"),
-                         i_ECLK=ClockSignal("sync2x"),
-                         i_SCLK=ClockSignal(),
-                         i_DQSW=dqsw,
-                         i_T0=~(dqs_oe | dqs_postamble),
-                         i_T1=~(dqs_oe | dqs_postamble),
-                         o_Q=dqs_oe_n
-                         ),
+                    i_RST=ResetSignal("dramsync"),
+                    i_ECLK=ClockSignal("sync2x"),
+                    i_SCLK=ClockSignal(),
+                    i_DQSW=dqsw,
+                    i_T0=~(dqs_oe | dqs_postamble),
+                    i_T1=~(dqs_oe | dqs_preamble),
+                    o_Q=dqs_oe_n),
                 Instance("BB",
                     i_I=dqs,
                     i_T=dqs_oe_n,
                     o_O=dqs_i,
-                    io_B=self.pads.dqs.io[i]
-                    )
+                    io_B=self.pads.dqs.io[i]),
             ]
 
             for j in range(8*i, 8*(i+1)):
@@ -368,72 +365,67 @@ 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:])
+                with m.If(bl8_chunk):
+                    m.d.sync += dq_o_data_muxed.eq(dq_o_data_d[4:])
+                with m.Else():
+                    m.d.sync += dq_o_data_muxed.eq(dq_o_data[:4])
+
                 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],
-                             o_Q=dq_o
-                             ),
+                        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],
+                        o_Q=dq_o),
                     Instance("DELAYF",
-                             p_DEL_MODE="DQS_ALIGNED_X2",
-                             i_LOADN=1,
-                             i_MOVE=0,
-                             i_DIRECTION=0,
-                             i_A=dq_i,
-                             o_Z=dq_i_delayed
-                             ),
+                        p_DEL_MODE="DQS_ALIGNED_X2",
+                        i_LOADN=1,
+                        i_MOVE=0,
+                        i_DIRECTION=0,
+                        i_A=dq_i,
+                        o_Z=dq_i_delayed),
                     Instance("IDDRX2DQA",
-                             i_RST=ResetSignal("dramsync"),
-                             i_ECLK=ClockSignal("sync2x"),
-                             i_SCLK=ClockSignal(),
-                             i_DQSR90=dqsr90,
-                             i_RDPNTR0=rdpntr[0],
-                             i_RDPNTR1=rdpntr[1],
-                             i_RDPNTR2=rdpntr[2],
-                             i_WRPNTR0=wrpntr[0],
-                             i_WRPNTR1=wrpntr[1],
-                             i_WRPNTR2=wrpntr[2],
-                             i_D=dq_i_delayed,
-                             o_Q0=dq_i_data[0],
-                             o_Q1=dq_i_data[1],
-                             o_Q2=dq_i_data[2],
-                             o_Q3=dq_i_data[3],
-                             ),
+                        i_RST=ResetSignal("dramsync"),
+                        i_ECLK=ClockSignal("sync2x"),
+                        i_SCLK=ClockSignal(),
+                        i_DQSR90=dqsr90,
+                        i_RDPNTR0=rdpntr[0],
+                        i_RDPNTR1=rdpntr[1],
+                        i_RDPNTR2=rdpntr[2],
+                        i_WRPNTR0=wrpntr[0],
+                        i_WRPNTR1=wrpntr[1],
+                        i_WRPNTR2=wrpntr[2],
+                        i_D=dq_i_delayed,
+                        o_Q0=dq_i_data[0],
+                        o_Q1=dq_i_data[1],
+                        o_Q2=dq_i_data[2],
+                        o_Q3=dq_i_data[3]),
                 ]
                 m.submodules += [
                     Instance("TSHX2DQA",
-                             i_RST=ResetSignal("dramsync"),
-                             i_ECLK=ClockSignal("sync2x"),
-                             i_SCLK=ClockSignal(),
-                             i_DQSW270=dqsw270,
-                             i_T0=~dq_oe,
-                             i_T1=~dq_oe,
-                             o_Q=dq_oe_n,
-                             ),
+                        i_RST=ResetSignal("dramsync"),
+                        i_ECLK=ClockSignal("sync2x"),
+                        i_SCLK=ClockSignal(),
+                        i_DQSW270=dqsw270,
+                        i_T0=~dq_oe,
+                        i_T1=~dq_oe,
+                        o_Q=dq_oe_n),
                     Instance("BB",
                         i_I=dq_o,
                         i_T=dq_oe_n,
                         o_O=dq_i,
-                        io_B=self.pads.dq.io[j]
-                        )
+                        io_B=self.pads.dq.io[j])
                 ]
                 m.d.sync += [
                     dfi.phases[1].rddata[j].eq(dq_i_data[0]),
@@ -460,6 +452,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
         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]
+        m.d.comb += dqs_re.eq(rddata_en[cl_sys_latency + 0] | rddata_en[cl_sys_latency + 1] | rddata_en[cl_sys_latency + 2])
 
         # Write Control Path -----------------------------------------------------------------------
         # Creates a shift register of write commands coming from the DFI interface. This shift register