litesata: use (some) settings from vivado 2015.1, try to follow all ug476 recommendat...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 5 May 2015 23:33:02 +0000 (01:33 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 5 May 2015 23:33:02 +0000 (01:33 +0200)
Works fine @ 3Gbps, still not working @6.0Gbps

misoclib/mem/litesata/example_designs/targets/bist.py
misoclib/mem/litesata/example_designs/test/bist.py
misoclib/mem/litesata/phy/__init__.py
misoclib/mem/litesata/phy/ctrl.py
misoclib/mem/litesata/phy/datapath.py
misoclib/mem/litesata/phy/k7/crg.py
misoclib/mem/litesata/phy/k7/trx.py

index 18b5333d900d85acfc117cee25b7c8c548fabd98..8b28dfe36cf21c66c1b8968e3ad453686b47eb5b 100644 (file)
@@ -19,7 +19,6 @@ from misoclib.mem.litesata import LiteSATA
 class _CRG(Module):
     def __init__(self, platform):
         self.clock_domains.cd_sys = ClockDomain()
-        self.reset = Signal()
 
         clk200 = platform.request("clk200")
         clk200_se = Signal()
@@ -49,7 +48,7 @@ class _CRG(Module):
                 p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4=
             ),
             Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
-            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset),
+            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset")),
         ]
 
 
@@ -106,7 +105,6 @@ class BISTSoC(SoC, AutoCSR):
 
         # SATA PHY/Core/Frontend
         self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
-        self.comb += self.crg.reset.eq(self.sata_phy.ctrl.need_reset)  # XXX FIXME
         self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True, with_bist_csr=True)
 
         # Status Leds
index 5b55a7007a7454f59a413eac3f2d33a74a3a5bd7..db8f7f86fd080562dcf154025033aa7c5caa54ab 100644 (file)
@@ -191,7 +191,7 @@ if __name__ == "__main__":
 
                 print("sector={:d}({:d}MB) wr_speed={:4.2f}MB/s rd_speed={:4.2f}MB/s errors={:d} retry={:d}".format(
                     sector,
-                    run_sectors*logical_sector_size/MB,
+                    int(run_sectors*logical_sector_size/MB),
                     write_speed/MB,
                     read_speed/MB,
                     write_errors + read_errors,
index edaea4038f178eb5aae29bd696bf086b32b26d22..4e952d4dea5af10e6dc234362f106ee7261973be 100644 (file)
@@ -7,6 +7,7 @@ class LiteSATAPHY(Module):
     def __init__(self, device, pads, revision, clk_freq):
         self.pads = pads
         self.revision = revision
+
         # Transceiver / Clocks
         if device[:3] == "xc7": # Kintex 7
             from misoclib.mem.litesata.phy.k7.trx import K7LiteSATAPHYTRX
@@ -14,8 +15,7 @@ class LiteSATAPHY(Module):
             self.submodules.trx = K7LiteSATAPHYTRX(pads, revision)
             self.submodules.crg = K7LiteSATAPHYCRG(pads, self.trx, revision, clk_freq)
         else:
-            msg = "Device" + device + "not (yet) supported."
-            raise NotImplementedError(msg)
+            raise NotImplementedError
 
         # Control
         self.submodules.ctrl = LiteSATAPHYCtrl(self.trx, self.crg, clk_freq)
index e73fb25857d83f77297e3a9cefcf385abe359ba8..3c53c6b380ab86dde990fd09a65de4a9c8bb67a8 100644 (file)
@@ -1,15 +1,10 @@
 from misoclib.mem.litesata.common import *
 
 
-def us(t, clk_freq):
-    clk_period_us = 1000000/clk_freq
-    return math.ceil(t/clk_period_us)
-
-
 class LiteSATAPHYCtrl(Module):
     def __init__(self, trx, crg, clk_freq):
+        self.clk_freq = clk_freq
         self.ready = Signal()
-        self.need_reset = Signal()
         self.sink = sink = Sink(phy_description(32))
         self.source = source = Source(phy_description(32))
 
@@ -20,47 +15,47 @@ class LiteSATAPHYCtrl(Module):
             sink.ack.eq(1)
         ]
 
-        retry_timeout = Timeout(us(10000, clk_freq))
-        align_timeout = Timeout(us(873, clk_freq))
+        retry_timeout = Timeout(self.us(10000))
+        align_timeout = Timeout(self.us(873))
         self.submodules += align_timeout, retry_timeout
 
         align_detect = Signal()
         non_align_cnt = Signal(4)
+        non_align_counter = Counter(4)
+        self.submodules += non_align_counter
 
-        self.fsm = fsm = FSM(reset_state="RESET")
+        self.fsm = fsm = InsertReset(FSM(reset_state="RESET"))
         self.submodules += fsm
+        self.comb += fsm.reset.eq(retry_timeout.reached | align_timeout.reached)
         fsm.act("RESET",
             trx.tx_idle.eq(1),
             retry_timeout.reset.eq(1),
             align_timeout.reset.eq(1),
+            non_align_counter.reset.eq(1),
             If(crg.ready,
                 NextState("COMINIT")
-            ),
+            )
         )
         fsm.act("COMINIT",
             trx.tx_idle.eq(1),
             trx.tx_cominit_stb.eq(1),
             If(trx.tx_cominit_ack & ~trx.rx_cominit_stb,
                 NextState("AWAIT_COMINIT")
-            ),
+            )
         )
         fsm.act("AWAIT_COMINIT",
             trx.tx_idle.eq(1),
             retry_timeout.ce.eq(1),
             If(trx.rx_cominit_stb,
                 NextState("AWAIT_NO_COMINIT")
-            ).Else(
-                If(retry_timeout.reached,
-                    NextState("RESET")
-                )
-            ),
+            )
         )
         fsm.act("AWAIT_NO_COMINIT",
             trx.tx_idle.eq(1),
             retry_timeout.reset.eq(1),
             If(~trx.rx_cominit_stb,
                 NextState("CALIBRATE")
-            ),
+            )
         )
         fsm.act("CALIBRATE",
             trx.tx_idle.eq(1),
@@ -71,34 +66,31 @@ class LiteSATAPHYCtrl(Module):
             trx.tx_comwake_stb.eq(1),
             If(trx.tx_comwake_ack,
                 NextState("AWAIT_COMWAKE")
-            ),
+            )
         )
         fsm.act("AWAIT_COMWAKE",
             trx.tx_idle.eq(1),
             retry_timeout.ce.eq(1),
             If(trx.rx_comwake_stb,
                 NextState("AWAIT_NO_COMWAKE")
-            ).Else(
-                If(retry_timeout.reached,
-                    NextState("RESET")
-                )
-            ),
+            )
         )
         fsm.act("AWAIT_NO_COMWAKE",
             trx.tx_idle.eq(1),
             If(~trx.rx_comwake_stb,
                 NextState("AWAIT_NO_RX_IDLE")
-            ),
+            )
         )
         fsm.act("AWAIT_NO_RX_IDLE",
             trx.tx_idle.eq(0),
             source.data.eq(0x4A4A4A4A),  # D10.2
             source.charisk.eq(0b0000),
+            align_timeout.ce.eq(1),
             If(~trx.rx_idle,
                 NextState("AWAIT_ALIGN"),
-                crg.reset.eq(1),
-                trx.pmarxreset.eq(1)
-            ),
+                crg.tx_reset.eq(1),
+                crg.rx_reset.eq(1)
+            )
         )
         fsm.act("AWAIT_ALIGN",
             trx.tx_idle.eq(0),
@@ -108,47 +100,39 @@ class LiteSATAPHYCtrl(Module):
             align_timeout.ce.eq(1),
             If(align_detect & ~trx.rx_idle,
                 NextState("SEND_ALIGN")
-            ).Elif(align_timeout.reached,
-                NextState("RESET")
-            ),
+            )
         )
         fsm.act("SEND_ALIGN",
             trx.tx_idle.eq(0),
             trx.rx_align.eq(1),
+            align_timeout.ce.eq(1),
             source.data.eq(primitives["ALIGN"]),
             source.charisk.eq(0b0001),
-            If(non_align_cnt == 3,
-                NextState("READY")
+            If(sink.stb,
+               If(sink.data[0:8] == 0x7C,
+                   non_align_counter.ce.eq(1)
+               ).Else(
+                   non_align_counter.reset.eq(1)
+               )
             ),
+            If(non_align_counter.value == 3,
+                NextState("READY")
+            )
         )
         fsm.act("READY",
             trx.tx_idle.eq(0),
             trx.rx_align.eq(1),
             source.data.eq(primitives["SYNC"]),
             source.charisk.eq(0b0001),
-            If(trx.rx_idle,
-                NextState("RESET")
-            ),
             self.ready.eq(1),
+            If(trx.rx_idle,
+               NextState("RESET"),
+                       )
         )
 
-        reset_timeout = Timeout(clk_freq//16)
-        self.submodules += reset_timeout
-        self.comb += [
-            reset_timeout.ce.eq(~self.ready),
-            self.need_reset.eq(reset_timeout.reached)
-        ]
+        self.comb +=  align_detect.eq(self.sink.stb &
+                                     (self.sink.data == primitives["ALIGN"]))
 
-        self.comb +=  \
-            align_detect.eq(self.sink.stb &
-                            (self.sink.data == primitives["ALIGN"]))
-        self.sync += \
-            If(fsm.ongoing("SEND_ALIGN"),
-                If(sink.stb,
-                    If(sink.data[0:8] == 0x7C,
-                        non_align_cnt.eq(non_align_cnt + 1)
-                    ).Else(
-                        non_align_cnt.eq(0)
-                    )
-                )
-            )
+    def us(self, t):
+        clk_period_us = 1000000/self.clk_freq
+        return math.ceil(t/clk_period_us)
index 847a0d8bf1801b0cbd307eb477f106534d88e724..f702ace40631cf90a5a3e91b07fc88bc6756f37e 100644 (file)
@@ -8,7 +8,7 @@ class LiteSATAPHYDatapathRX(Module):
 
         # # #
 
-    # width convertion (16 to 32) and byte alignment
+        # width convertion (16 to 32) and byte alignment
         byte_alignment = Signal()
         last_charisk = Signal(2)
         last_data = Signal(16)
@@ -38,13 +38,13 @@ class LiteSATAPHYDatapathRX(Module):
             converter.reset.eq(converter.source.charisk[2:] != 0)
         ]
 
-    # clock domain crossing
-        # (sata_gen3) 300MHz sata_rx clk to sys_clk
-        # (sata_gen2) 150MHz sata_rx clk to sys_clk
-        # (sata_gen1) 75MHz sata_rx clk to sys_clk
-        # requirements:
-        # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
-        # source destination is always able to accept data (ack always 1)
+        # clock domain crossing
+        #   (sata_gen3) 300MHz sata_rx clk to sys_clk
+        #   (sata_gen2) 150MHz sata_rx clk to sys_clk
+        #   (sata_gen1) 75MHz sata_rx clk to sys_clk
+        #   requirements:
+        #     due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
+        #     source destination is always able to accept data (ack always 1)
         fifo = AsyncFIFO(phy_description(32), 4)
         fifo = RenameClockDomains(fifo, {"write": "sata_rx", "read": "sys"})
         self.submodules += fifo
@@ -61,18 +61,18 @@ class LiteSATAPHYDatapathTX(Module):
 
         # # #
 
-    # clock domain crossing
-        # (sata_gen3) sys_clk to 300MHz sata_tx clk
-        # (sata_gen2) sys_clk to 150MHz sata_tx clk
-        # (sata_gen1) sys_clk to 75MHz sata_tx clk
-        # requirements:
-        # source destination is always able to accept data (ack always 1)
+        # clock domain crossing
+        #   (sata_gen3) sys_clk to 300MHz sata_tx clk
+        #   (sata_gen2) sys_clk to 150MHz sata_tx clk
+        #   (sata_gen1) sys_clk to 75MHz sata_tx clk
+        #   requirements:
+        #     source destination is always able to accept data (ack always 1)
         fifo = AsyncFIFO(phy_description(32), 4)
         fifo = RenameClockDomains(fifo, {"write": "sys", "read": "sata_tx"})
         self.submodules += fifo
         self.comb += Record.connect(sink, fifo.sink)
 
-    # width convertion (32 to 16)
+        # width convertion (32 to 16)
         converter = Converter(phy_description(32),
                               phy_description(16),
                               reverse=False)
@@ -143,7 +143,7 @@ class LiteSATAPHYDatapath(Module):
 
         # # #
 
-    # TX path
+        # TX path
         align_inserter = LiteSATAPHYAlignInserter(ctrl)
         mux = Multiplexer(phy_description(32), 2)
         tx = LiteSATAPHYDatapathTX()
@@ -157,7 +157,7 @@ class LiteSATAPHYDatapath(Module):
             Record.connect(tx.source, trx.sink)
         ]
 
-    # RX path
+        # RX path
         rx = LiteSATAPHYDatapathRX()
         demux = Demultiplexer(phy_description(32), 2)
         align_remover = LiteSATAPHYAlignRemover()
index 86aeb86cb977df00f65cbdd2f79070a9d1518bdd..73a7d9668bd885ae5a18fc182d035c6e1ec71f9e 100644 (file)
@@ -3,15 +3,17 @@ from misoclib.mem.litesata.common import *
 
 class K7LiteSATAPHYCRG(Module):
     def __init__(self, pads, gtx, revision, clk_freq):
-        self.reset = Signal()
+        self.tx_reset = Signal()
+        self.rx_reset = Signal()
         self.ready = Signal()
 
         self.clock_domains.cd_sata_tx = ClockDomain()
         self.clock_domains.cd_sata_rx = ClockDomain()
 
-    # CPLL
-        # (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
-        # (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is decreased with output dividers.
+        # CPLL
+        #   (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
+        #   (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is
+        #   decreased with output dividers.
         refclk = Signal()
         self.specials += Instance("IBUFDS_GTE2",
             i_CEB=0,
@@ -21,19 +23,19 @@ class K7LiteSATAPHYCRG(Module):
         )
         self.comb += gtx.gtrefclk0.eq(refclk)
 
-    # TX clocking
-        # (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
-        # (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits)
-        # (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits)
+        # TX clocking
+        #   (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
+        #   (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits)
+        #   (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits)
         mmcm_reset = Signal()
         mmcm_locked = Signal()
         mmcm_fb = Signal()
         mmcm_clk_i = Signal()
         mmcm_clk0_o = Signal()
         mmcm_div_config = {
-            "sata_gen1":     16.0,
+            "sata_gen1":   16.0,
             "sata_gen2":    8.0,
-            "sata_gen3":     4.0
+            "sata_gen3":    4.0
             }
         mmcm_div = mmcm_div_config[revision]
         self.specials += [
@@ -60,10 +62,10 @@ class K7LiteSATAPHYCRG(Module):
             gtx.txusrclk2.eq(self.cd_sata_tx.clk)
         ]
 
-    # RX clocking
-        # (sata_gen3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK
-        # (sata_gen2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
-        # (sata_gen1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
+        # RX clocking
+        #   (sata_gen3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK
+        #   (sata_gen2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
+        #   (sata_gen1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
         self.specials += [
             Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk),
         ]
@@ -72,85 +74,154 @@ class K7LiteSATAPHYCRG(Module):
             gtx.rxusrclk2.eq(self.cd_sata_rx.clk)
         ]
 
-    # Configuration Reset
-        # After configuration, GTX's resets have to stay low for at least 500ns
-        # See AR43482
-        reset_en = Signal()
-        clk_period_ns = 1000000000/clk_freq
-        reset_en_cnt_max = math.ceil(500/clk_period_ns)
-        reset_en_cnt = Signal(max=reset_en_cnt_max, reset=reset_en_cnt_max-1)
-        self.sync += \
-            If(self.reset,
-                reset_en_cnt.eq(reset_en_cnt.reset)
-            ).Elif(~reset_en,
-                reset_en_cnt.eq(reset_en_cnt-1)
+        # Configuration Reset
+        #   After configuration, GTX's resets have to stay low for at least 500ns
+        #   See AR43482
+        startup_cycles = math.ceil(500*clk_freq/1000000000)
+        startup_wait = Timeout(startup_cycles)
+        self.submodules += startup_wait
+        self.comb += [
+            startup_wait.reset.eq(self.tx_reset | self.rx_reset),
+            startup_wait.ce.eq(1)
+        ]
+
+        # TX Startup FSM
+        self.tx_ready = Signal()
+        tx_startup_fsm = InsertReset(FSM(reset_state="IDLE"))
+        self.submodules += tx_startup_fsm
+        # Wait 500ns of AR43482
+        tx_startup_fsm.act("IDLE",
+            If(startup_wait.reached,
+                NextState("RESET_ALL"),
             )
-        self.comb += reset_en.eq(reset_en_cnt == 0)
-
-    # TX Reset FSM
-        tx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
-        self.submodules += tx_reset_fsm
-        self.comb += tx_reset_fsm.reset.eq(self.reset)
-        tx_reset_fsm.act("IDLE",
-            If(reset_en,
-                NextState("RESET_GTX"),
+        )
+        # Reset CPLL, MMCM, GTX
+        tx_startup_fsm.act("RESET_ALL",
+            gtx.cpllreset.eq(1),
+            mmcm_reset.eq(1),
+            gtx.gttxreset.eq(1),
+            NextState("RELEASE_CPLL"),
+        )
+        # Release CPLL reset and wait for lock
+        tx_startup_fsm.act("RELEASE_CPLL",
+            mmcm_reset.eq(1),
+            gtx.gttxreset.eq(1),
+            If(gtx.cplllock,
+                NextState("RELEASE_MMCM"),
             )
         )
-        tx_reset_fsm.act("RESET_GTX",
+        # Release MMCM reset and wait for lock
+        tx_startup_fsm.act("RELEASE_MMCM",
             gtx.gttxreset.eq(1),
-            If(gtx.cplllock & mmcm_locked,
+            If(mmcm_locked,
                 NextState("RELEASE_GTX")
             )
         )
-        tx_reset_fsm.act("RELEASE_GTX",
+        # Release GTX reset and wait for GTX resetdone
+        # (from UG476, GTX is reseted on falling edge
+        # of gttxreset)
+        tx_startup_fsm.act("RELEASE_GTX",
             gtx.txuserrdy.eq(1),
             If(gtx.txresetdone,
                 NextState("READY")
             )
         )
-        tx_reset_fsm.act("READY",
-            gtx.txuserrdy.eq(1)
+        # Start Delay alignment (Pulse)
+        tx_startup_fsm.act("ALIGN",
+            gtx.txuserrdy.eq(1),
+            gtx.txdlyreset.eq(1),
+            NextState("WAIT_ALIGN")
         )
+        # Wait Delay alignment
+        tx_startup_fsm.act("WAIT_ALIGN",
+            gtx.txuserrdy.eq(1),
+            If(gtx.txdlyresetdone,
+                NextState("READY")
+            )
+        )
+        tx_startup_fsm.act("READY",
+            gtx.txuserrdy.eq(1),
+            self.tx_ready.eq(1)
+        )
+
+        tx_ready_timeout = Timeout(1*clk_freq//1000)
+        self.submodules += tx_ready_timeout
+        self.comb += [
+            tx_ready_timeout.reset.eq(self.tx_reset | self.tx_ready),
+            tx_ready_timeout.ce.eq(~self.tx_ready),
+            tx_startup_fsm.reset.eq(self.tx_reset | tx_ready_timeout.reached),
+        ]
+
+
+        # RX Startup FSM
+        self.rx_ready = Signal()
+        rx_startup_fsm = InsertReset(FSM(reset_state="IDLE"))
+        self.submodules += rx_startup_fsm
 
-    # RX Reset FSM
-        rx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
-        self.submodules += rx_reset_fsm
-        self.comb += rx_reset_fsm.reset.eq(self.reset)
+        cdr_stable = Timeout(2048)
+        self.submodules += cdr_stable
+        self.comb += cdr_stable.ce.eq(1),
 
-        rx_reset_fsm.act("IDLE",
-            If(reset_en,
+        # Wait 500ns of AR43482
+        rx_startup_fsm.act("IDLE",
+            cdr_stable.reset.eq(1),
+            If(startup_wait.reached,
                 NextState("RESET_GTX"),
             )
         )
-        rx_reset_fsm.act("RESET_GTX",
+        # Reset GTX
+        rx_startup_fsm.act("RESET_GTX",
             gtx.gtrxreset.eq(1),
-            If(gtx.cplllock & mmcm_locked,
-                NextState("RELEASE_GTX")
+            NextState("WAIT_CPLL")
+        )
+        # Wait for CPLL lock
+        rx_startup_fsm.act("WAIT_CPLL",
+            gtx.gtrxreset.eq(1),
+            If(gtx.cplllock,
+                NextState("RELEASE_GTX"),
+                cdr_stable.reset.eq(1)
+            )
+        )
+        # Release GTX reset and wait for GTX resetdone
+        # (from UG476, GTX is reseted on falling edge
+        # of gttxreset)
+        rx_startup_fsm.act("RELEASE_GTX",
+            gtx.rxuserrdy.eq(1),
+            If(gtx.rxresetdone &  cdr_stable.reached,
+                NextState("ALIGN")
             )
         )
-        rx_reset_fsm.act("RELEASE_GTX",
+        # Start Delay alignment (Pulse)
+        rx_startup_fsm.act("ALIGN",
             gtx.rxuserrdy.eq(1),
-            If(gtx.rxresetdone,
+            gtx.rxdlyreset.eq(1),
+            NextState("WAIT_ALIGN")
+        )
+        # Wait Delay alignment
+        rx_startup_fsm.act("WAIT_ALIGN",
+            gtx.rxuserrdy.eq(1),
+            If(gtx.rxdlyresetdone,
                 NextState("READY")
             )
         )
-        rx_reset_fsm.act("READY",
-            gtx.rxuserrdy.eq(1)
+        rx_startup_fsm.act("READY",
+            gtx.rxuserrdy.eq(1),
+            self.rx_ready.eq(1)
         )
 
-    # Ready
-        self.tx_ready = tx_reset_fsm.ongoing("READY")
-        self.rx_ready = rx_reset_fsm.ongoing("READY")
-        self.comb += self.ready.eq(self.tx_ready & self.rx_ready)
-
-    # Reset PLL
-        self.comb += gtx.cpllreset.eq(ResetSignal() | self.reset | ~reset_en)
+        rx_ready_timeout = Timeout(1*clk_freq//1000)
+        self.submodules += rx_ready_timeout
+        self.comb += [
+            rx_ready_timeout.reset.eq(self.rx_reset | self.rx_ready),
+            rx_ready_timeout.ce.eq(~self.rx_ready),
+            rx_startup_fsm.reset.eq(self.rx_reset | rx_ready_timeout.reached),
+        ]
 
-    # Reset MMCM
-        self.comb += mmcm_reset.eq(ResetSignal() | self.reset | ~gtx.cplllock)
+        # Ready
+        self.comb += self.ready.eq(self.tx_ready & self.rx_ready)
 
-    # Reset for SATA TX/RX clock domains
+        # Reset for SATA TX/RX clock domains
         self.specials += [
-            AsyncResetSynchronizer(self.cd_sata_tx, ~self.tx_ready),
-            AsyncResetSynchronizer(self.cd_sata_rx, ~self.rx_ready),
+            AsyncResetSynchronizer(self.cd_sata_tx, ~(gtx.cplllock & mmcm_locked) | self.tx_reset),
+            AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | self.rx_reset),
         ]
index 6e3fbc57580f60106f3fda664b82f81d525a72c5..628e4506b308364ce8b5056fb4cc520eec0146e1 100644 (file)
@@ -21,23 +21,39 @@ class _RisingEdge(Module):
         self.comb += o.eq(i & ~i_d)
 
 
+class _LowPassFilter(Module):
+    def __init__(self, i, o, cycles):
+        i_d = Signal()
+        self.submodules.timeout = Timeout(cycles)
+        self.sync += [
+            i_d.eq(i),
+            If(self.timeout.reached,
+                o.eq(i_d)
+            )
+        ]
+        self.comb += [
+            self.timeout.reset.eq(i != i_d),
+            self.timeout.ce.eq(1)
+        ]
+
+
 class K7LiteSATAPHYTRX(Module):
     def __init__(self, pads, revision):
     # Common signals
 
         # control
-        self.tx_idle = Signal()            #i
+        self.tx_idle = Signal()         #i
 
         self.tx_cominit_stb = Signal()  #i
         self.tx_cominit_ack = Signal()  #o
         self.tx_comwake_stb = Signal()  #i
-        self.tx_comwake_ack = Signal()    #o
+        self.tx_comwake_ack = Signal()  #o
 
-        self.rx_idle = Signal()            #o
+        self.rx_idle = Signal()         #o
         self.rx_align = Signal()        #i
 
-        self.rx_cominit_stb = Signal()    #o
-        self.rx_comwake_stb = Signal()    #o
+        self.rx_cominit_stb = Signal()  #o
+        self.rx_comwake_stb = Signal()  #o
 
         # datapath
         self.sink = Sink(phy_description(16))
@@ -53,15 +69,12 @@ class K7LiteSATAPHYTRX(Module):
 
         # Receive Ports
         self.rxuserrdy = Signal()
-        self.rxalign = Signal()
 
         # Receive Ports - 8b10b Decoder
         self.rxcharisk = Signal(2)
-        self.rxdisperr = Signal(2)
 
         # Receive Ports - RX Data Path interface
         self.gtrxreset = Signal()
-        self.pmarxreset = Signal()
         self.rxdata = Signal(16)
         self.rxoutclk = Signal()
         self.rxusrclk = Signal()
@@ -72,6 +85,8 @@ class K7LiteSATAPHYTRX(Module):
 
         # Receive Ports - RX PLL Ports
         self.rxresetdone = Signal()
+        self.rxdlyreset = Signal()
+        self.rxdlyresetdone = Signal()
 
         # Receive Ports - RX Ports for SATA
         self.rxcominitdet = Signal()
@@ -92,6 +107,8 @@ class K7LiteSATAPHYTRX(Module):
 
         # Transmit Ports - TX PLL Ports
         self.txresetdone = Signal()
+        self.txdlyreset = Signal()
+        self.txdlyresetdone = Signal()
 
         # Transmit Ports - TX Ports for PCI Express
         self.txelecidle = Signal(reset=1)
@@ -100,8 +117,6 @@ class K7LiteSATAPHYTRX(Module):
         self.txcomfinish = Signal()
         self.txcominit = Signal()
         self.txcomwake = Signal()
-        self.txrate = Signal(3)
-        self.rxcdrlock = Signal()
 
     # Config at startup
         div_config = {
@@ -125,7 +140,6 @@ class K7LiteSATAPHYTRX(Module):
             self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
             self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
             self.rx_idle.eq(self.rxelecidle),
-            self.rxalign.eq(self.rx_align),
             self.rx_cominit_stb.eq(self.rxcominitdet),
             self.rx_comwake_stb.eq(self.rxcomwakedet),
         ]
@@ -150,16 +164,19 @@ class K7LiteSATAPHYTRX(Module):
         txelecidle = Signal(reset=1)
         txcominit = Signal()
         txcomwake = Signal()
-        txrate = Signal(3)
+        txdlyreset = Signal()
+        txdlyresetdone = Signal()
+        gttxreset = Signal()
 
         self.specials += [
             MultiReg(self.txuserrdy, txuserrdy, "sata_tx"),
             MultiReg(self.txelecidle, txelecidle, "sata_tx"),
-            MultiReg(self.txrate, txrate, "sata_tx")
+            MultiReg(self.gttxreset, gttxreset, "sata_tx"),
         ]
         self.submodules += [
             _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
             _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
+            _PulseSynchronizer(self.txdlyreset, "sys", txdlyreset, "sata_tx"),
         ]
 
         # sata_tx clk --> sys clk
@@ -168,6 +185,7 @@ class K7LiteSATAPHYTRX(Module):
 
         self.specials += [
             MultiReg(txresetdone, self.txresetdone, "sys"),
+            MultiReg(txdlyresetdone, self.txdlyresetdone, "sys"),
         ]
 
         self.submodules += [
@@ -176,43 +194,35 @@ class K7LiteSATAPHYTRX(Module):
 
         # sys clk --> sata_rx clk
         rxuserrdy = Signal()
+        rxdlyreset = Signal()
 
         self.specials += [
             MultiReg(self.rxuserrdy, rxuserrdy, "sata_rx"),
         ]
 
+        self.submodules += [
+            _PulseSynchronizer(self.rxdlyreset, "sys", rxdlyreset, "sata_rx"),
+        ]
+
         # sata_rx clk --> sys clk
         rxelecidle = Signal()
         rxelecidle_i = Signal()
-        rxelecidle_cnt_i = Signal(9)
         rxresetdone = Signal()
         rxcominitdet = Signal()
         rxcomwakedet = Signal()
         rxratedone = Signal()
-        rxcdrlock = Signal()
+        rxdlyresetdone = Signal()
 
         self.specials += [
             MultiReg(rxelecidle, rxelecidle_i, "sys"),
             MultiReg(rxresetdone, self.rxresetdone, "sys"),
             MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
             MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
-            MultiReg(rxcdrlock, self.rxcdrlock, "sys"),
-        ]
-
-        self.sync += [
-            If(rxelecidle_i != self.rxelecidle,
-                If(rxelecidle_cnt_i == 0,
-                    self.rxelecidle.eq(rxelecidle_i),
-                    rxelecidle_cnt_i.eq(255)
-                ).Else(
-                    rxelecidle_cnt_i.eq(rxelecidle_cnt_i-1)
-                )
-            ).Else(
-                rxelecidle_cnt_i.eq(255)
-            )
+            MultiReg(rxdlyresetdone, self.rxdlyresetdone, "sys"),
         ]
 
-        self.rxbyteisaligned = Signal()
+        rxelecidle_filter = _LowPassFilter(rxelecidle_i, self.rxelecidle, 256)
+        self.submodules += rxelecidle_filter
 
     # QPLL input clock
         self.qpllclk = Signal()
@@ -230,7 +240,7 @@ class K7LiteSATAPHYTRX(Module):
                 # RX Byte and Word Alignment Attributes
                     "p_ALIGN_COMMA_DOUBLE": "FALSE",
                     "p_ALIGN_COMMA_ENABLE": ones(10),
-                    "p_ALIGN_COMMA_WORD": 2,
+                    "p_ALIGN_COMMA_WORD": 1,
                     "p_ALIGN_MCOMMA_DET": "TRUE",
                     "p_ALIGN_MCOMMA_VALUE": 0b1010000011,
                     "p_ALIGN_PCOMMA_DET": "TRUE",
@@ -263,9 +273,9 @@ class K7LiteSATAPHYTRX(Module):
                     "p_CLK_CORRECT_USE": "FALSE",
                     "p_CLK_COR_SEQ_2_ENABLE": ones(4),
                     "p_CLK_COR_SEQ_2_1": 0b0100000000,
-                    "p_CLK_COR_SEQ_2_2": 0,
-                    "p_CLK_COR_SEQ_2_3": 0,
-                    "p_CLK_COR_SEQ_2_4": 0,
+                    "p_CLK_COR_SEQ_2_2": 0b0000000000,
+                    "p_CLK_COR_SEQ_2_3": 0b0000000000,
+                    "p_CLK_COR_SEQ_2_4": 0b0000000000,
 
                 # RX Channel Bonding Attributes
                     "p_CHAN_BOND_KEEP_ALIGN": "FALSE",
@@ -314,7 +324,7 @@ class K7LiteSATAPHYTRX(Module):
                     "p_RX_CM_TRIM": 0b010,
                     "p_RX_DEBUG_CFG": 0,
                     "p_RX_OS_CFG": 0b10000000,
-                    "p_TERM_RCAL_CFG": 0,
+                    "p_TERM_RCAL_CFG": 0b10000,
                     "p_TERM_RCAL_OVRD": 0,
                     "p_TST_RSV": 0,
                     "p_RX_CLK25_DIV": 6,
@@ -330,8 +340,8 @@ class K7LiteSATAPHYTRX(Module):
                 # RX Buffer Attributes
                     "p_RXBUF_ADDR_MODE": "FAST",
                     "p_RXBUF_EIDLE_HI_CNT": 0b1000,
-                    "p_RXBUF_EIDLE_LO_CNT": 0,
-                    "p_RXBUF_EN": "TRUE",
+                    "p_RXBUF_EIDLE_LO_CNT": 0b0000,
+                    "p_RXBUF_EN": "FALSE",
                     "p_RX_BUFFER_CFG": 0,
                     "p_RXBUF_RESET_ON_CB_CHANGE": "TRUE",
                     "p_RXBUF_RESET_ON_COMMAALIGN": "FALSE",
@@ -397,7 +407,7 @@ class K7LiteSATAPHYTRX(Module):
                     "p_TRANS_TIME_RATE": 0x0e,
 
                 # TX Buffer Attributes
-                    "p_TXBUF_EN": "TRUE",
+                    "p_TXBUF_EN": "FALSE",
                     "p_TXBUF_RESET_ON_RATE_CHANGE": "TRUE",
                     "p_TXDLY_CFG": 0x1f,
                     "p_TXDLY_LCFG": 0x030,
@@ -405,7 +415,7 @@ class K7LiteSATAPHYTRX(Module):
                     "p_TXPH_CFG": 0x0780,
                     "p_TXPHDLY_CFG": 0x084020,
                     "p_TXPH_MONITOR_SEL": 0,
-                    "p_TX_XCLK_SEL": "TXOUT",
+                    "p_TX_XCLK_SEL": "TXUSR",
 
                 # FPGA TX Interface Attributes
                     "p_TX_DATA_WIDTH": 20,
@@ -569,7 +579,7 @@ class K7LiteSATAPHYTRX(Module):
                 # Receive Ports - CDR Ports
                     i_RXCDRFREQRESET=0,
                     i_RXCDRHOLD=0,
-                    o_RXCDRLOCK=rxcdrlock,
+                    #o_RXCDRLOCK=,
                     i_RXCDROVRDEN=0,
                     i_RXCDRRESET=0,
                     i_RXCDRRESETRSV=0,
@@ -595,7 +605,7 @@ class K7LiteSATAPHYTRX(Module):
                     i_RXPRBSCNTRESET=0,
 
                 # Receive Ports - RX  Equalizer Ports
-                    i_RXDFEXYDEN=0,
+                    i_RXDFEXYDEN=1,
                     i_RXDFEXYDHOLD=0,
                     i_RXDFEXYDOVRDEN=0,
 
@@ -610,12 +620,12 @@ class K7LiteSATAPHYTRX(Module):
                 # Receive Ports - RX Buffer Bypass Ports
                     i_RXBUFRESET=0,
                     #o_RXBUFSTATUS=,
-                    i_RXDDIEN=0,
-                    i_RXDLYBYPASS=1,
+                    i_RXDDIEN=1,
+                    i_RXDLYBYPASS=0,
                     i_RXDLYEN=0,
                     i_RXDLYOVRDEN=0,
-                    i_RXDLYSRESET=0,
-                    #o_RXDLYSRESETDONE=0,
+                    i_RXDLYSRESET=rxdlyreset,
+                    o_RXDLYSRESETDONE=rxdlyresetdone,
                     i_RXPHALIGN=0,
                     #o_RXPHALIGNDONE=,
                     i_RXPHALIGNEN=0,
@@ -627,7 +637,7 @@ class K7LiteSATAPHYTRX(Module):
                     #o_RXSTATUS=,
 
                 # Receive Ports - RX Byte and Word Alignment Ports
-                    o_RXBYTEISALIGNED=self.rxbyteisaligned,
+                    #o_RXBYTEISALIGNED=,
                     #o_RXBYTEREALIGN=,
                     #o_RXCOMMADET=,
                     i_RXCOMMADETEN=1,
@@ -651,7 +661,7 @@ class K7LiteSATAPHYTRX(Module):
                     i_RXDFEAGCOVRDEN=0,
                     i_RXDFECM1EN=0,
                     i_RXDFELFHOLD=0,
-                    i_RXDFELFOVRDEN=1,
+                    i_RXDFELFOVRDEN=0,
                     i_RXDFELPMRESET=0,
                     i_RXDFETAP2HOLD=0,
                     i_RXDFETAP2OVRDEN=0,
@@ -699,7 +709,7 @@ class K7LiteSATAPHYTRX(Module):
                     i_GTRXRESET=self.gtrxreset,
                     i_RXOOBRESET=0,
                     i_RXPCSRESET=0,
-                    i_RXPMARESET=self.pmarxreset,
+                    i_RXPMARESET=0,
 
                 # Receive Ports - RX Margin Analysis ports
                     i_RXLPMEN=0,
@@ -750,7 +760,7 @@ class K7LiteSATAPHYTRX(Module):
 
                 # TX Initialization and Reset Ports
                     i_CFGRESET=0,
-                    i_GTTXRESET=self.gttxreset,
+                    i_GTTXRESET=gttxreset,
                     #o_PCSRSVDOUT=,
                     i_TXUSERRDY=txuserrdy,
 
@@ -769,19 +779,19 @@ class K7LiteSATAPHYTRX(Module):
                 # Transmit Ports - PCI Express Ports
                     i_TXELECIDLE=txelecidle,
                     i_TXMARGIN=0,
-                    i_TXRATE=txrate,
+                    i_TXRATE=0,
                     i_TXSWING=0,
 
                 # Transmit Ports - Pattern Generator Ports
                     i_TXPRBSFORCEERR=0,
 
                 # Transmit Ports - TX Buffer Bypass Ports
-                    i_TXDLYBYPASS=1,
+                    i_TXDLYBYPASS=0,
                     i_TXDLYEN=0,
                     i_TXDLYHOLD=0,
                     i_TXDLYOVRDEN=0,
-                    i_TXDLYSRESET=0,
-                    #o_TXDLYSRESETDONE=,
+                    i_TXDLYSRESET=txdlyreset,
+                    o_TXDLYSRESETDONE=txdlyresetdone,
                     i_TXDLYUPDOWN=0,
                     i_TXPHALIGN=0,
                     #o_TXPHALIGNDONE=txphaligndone,
@@ -815,7 +825,7 @@ class K7LiteSATAPHYTRX(Module):
                     o_TXOUTCLK=self.txoutclk,
                     #o_TXOUTCLKFABRIC=,
                     #o_TXOUTCLKPCS=,
-                    i_TXOUTCLKSEL=0b11,  # ??
+                    i_TXOUTCLKSEL=0b11,
                     #o_TXRATEDONE=,
                 # Transmit Ports - TX Gearbox Ports
                     i_TXCHARISK=self.txcharisk,