link: check CRC on RX path
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 25 Dec 2014 12:11:22 +0000 (13:11 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 25 Dec 2014 16:15:35 +0000 (17:15 +0100)
lib/sata/command/__init__.py
lib/sata/common.py
lib/sata/link/__init__.py
lib/sata/link/crc.py
lib/sata/test/hdd.py
lib/sata/transport/__init__.py

index 925ef08f9b801ef7c91e0776a4c575917b55e7c4..42ba8931bc7dce7441f9d6c42026762511d0863c 100644 (file)
@@ -2,14 +2,11 @@ from lib.sata.common import *
 
 tx_to_rx = [
        ("write", 1),
-       ("read", 1),
-       ("count", 4)
+       ("read", 1)
 ]
 
 rx_to_tx = [
-       ("dma_activate", 1),
-       ("data", 1),
-       ("reg_d2h", 1)
+       ("dma_activate", 1)
 ]
 
 class SATACommandTX(Module):
@@ -88,8 +85,7 @@ class SATACommandTX(Module):
                self.comb += [
                        If(sink.stb,
                                to_rx.write.eq(sink.write),
-                               to_rx.read.eq(sink.read),
-                               to_rx.count.eq(sink.count)
+                               to_rx.read.eq(sink.read)
                        )
                ]
 
@@ -139,7 +135,8 @@ class SATACommandRX(Module):
                fsm.act("PRESENT_WRITE_RESPONSE",
                        cmd_fifo.sink.stb.eq(1),
                        cmd_fifo.sink.write.eq(1),
-                       cmd_fifo.sink.success.eq(1),
+                       cmd_fifo.sink.success.eq(~transport.source.error),
+                       cmd_fifo.sink.failed.eq(transport.source.error),
                        If(cmd_fifo.sink.stb & cmd_fifo.sink.ack,
                                NextState("IDLE")
                        )
@@ -163,6 +160,13 @@ class SATACommandRX(Module):
                                NextState("WAIT_READ_REG_D2H")
                        )
                )
+               read_error = Signal()
+               self.sync += \
+                       If(fsm.ongoing("IDLE"),
+                               read_error.eq(1)
+                       ).Elif(transport.source.stb & transport.source.ack & transport.source.eop,
+                               read_error.eq(transport.source.error)
+                       )
                fsm.act("WAIT_READ_REG_D2H",
                        transport.source.ack.eq(1),
                        If(transport.source.stb,
@@ -174,8 +178,8 @@ class SATACommandRX(Module):
                fsm.act("PRESENT_READ_RESPONSE",
                        cmd_fifo.sink.stb.eq(1),
                        cmd_fifo.sink.read.eq(1),
-                       cmd_fifo.sink.success.eq(1),
-                       cmd_fifo.sink.failed.eq(0),
+                       cmd_fifo.sink.success.eq(~read_error),
+                       cmd_fifo.sink.failed.eq(read_error),
                        If(~cmd_fifo.fifo.readable, # Note: simulate a fifo with depth=1
                                If(cmd_fifo.sink.stb & cmd_fifo.sink.ack,
                                        If(cmd_fifo.sink.failed,
index 463e9cd644c13236aff47881c39a5ded32ce5c9d..98dd3001f337152e4697fbde92ffd30dc0f25efa 100644 (file)
@@ -136,7 +136,8 @@ def transport_rx_description(dw):
                ("lba", 48),
                ("device", 8),
                ("count", 16),
-               ("data", dw)
+               ("data", dw),
+               ("error", 1)
        ]
        return EndpointDescription(layout, packetized=True)
 
index d4f838cd684f0a9aa0ac46536b073a0302344051..e55c2ab22ddb477f2a2b2f9c13d7ba8cd2449e1d 100644 (file)
@@ -146,6 +146,12 @@ class SATALinkRX(Module):
                        )
                self.comb += eop.eq(det == primitives["EOF"])
 
+               crc_error = Signal()
+               self.sync += \
+                       If(crc.source.stb & crc.source.eop & crc.source.ack,
+                               crc_error.eq(crc.source.error)
+                       )
+
                # small fifo to manage HOLD
                self.fifo = SyncFIFO(link_description(32), 32)
 
@@ -195,17 +201,31 @@ class SATALinkRX(Module):
                        )
                )
                fsm.act("EOF",
+                       insert.eq(primitives["R_IP"]),
                        If(det == primitives["WTRM"],
                                NextState("WTRM")
                        )
                )
                fsm.act("WTRM",
-                       # XXX: check CRC result to return R_ERR or R_OK
+                       insert.eq(primitives["R_IP"]),
+                       If(~crc_error,
+                               NextState("R_OK")
+                       ).Else(
+                               NextState("R_ERR")
+                       )
+               )
+               fsm.act("R_OK",
                        insert.eq(primitives["R_OK"]),
                        If(det == primitives["SYNC"],
                                NextState("IDLE")
                        )
                )
+               fsm.act("R_ERR",
+                       insert.eq(primitives["R_ERR"]),
+                       If(det == primitives["SYNC"],
+                               NextState("IDLE")
+                       )
+               )
 
                # to TX
                self.comb += [
index 72157ce535abfebe0580cf7b8a2d394d2425d48b..4d6c67b672c7f0316cf61a0c40e72077212f0e17 100644 (file)
@@ -87,7 +87,7 @@ class SATACRC(Module):
        width = 32
        polynom = 0x04C11DB7
        init = 0x52325032
-       check = 0xC704DD7B
+       check = 0x00000000
        def __init__(self, dw=32):
                self.d = Signal(self.width)
                self.value = Signal(self.width)
@@ -112,4 +112,4 @@ class SATACRCInserter(CRCInserter):
 
 class SATACRCChecker(CRCChecker):
        def __init__(self, description):
-               CRCChecker.__init__(self, SATACRC, description)
\ No newline at end of file
+               CRCChecker.__init__(self, SATACRC, description)
index c601c04251faca5a68a578dcb67e8d0632158e35..8783d06915d295630baaf1626f3a7eb2964248bf 100644 (file)
@@ -189,7 +189,8 @@ class LinkLayer(Module):
                                self.tx_packet.done = True
                        elif dword == primitives["R_ERR"]:
                                self.tx_packet.done = True
-                       self.phy.send(primitives["SYNC"])
+                       if self.tx_packet.done:
+                               self.phy.send(primitives["SYNC"])
 
        def insert_cont(self):
                self.tx_lasts.pop(0)
index f4cb1f6eac0078e9b543cddf75bddbcc7d1f1cf2..6ef14e68f1a6576d1bc036ee50e64a540080fe6c 100644 (file)
@@ -200,6 +200,7 @@ class SATATransportRX(Module):
                        _decode_cmd(encoded_cmd, fis_data_layout, source),
                        source.sop.eq(data_sop),
                        source.eop.eq(link.source.eop),
+                       source.error.eq(link.source.error),
                        source.data.eq(link.source.d),
                        link.source.ack.eq(source.ack),
                        If(source.stb & source.eop & source.ack,