link: manage CONT on RX path
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 3 Dec 2014 10:50:31 +0000 (11:50 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 3 Dec 2014 10:50:31 +0000 (11:50 +0100)
lib/sata/link/__init__.py
lib/sata/link/cont.py
lib/sata/link/test/bfm.py

index 07df3adc499532d9b2afff79cc64d8fc8d50454b..0570916fdc74ee4b788fdaf025e3b61e0ea28ec5 100644 (file)
@@ -4,10 +4,11 @@ from migen.genlib.fsm import FSM, NextState
 from lib.sata.std import *
 from lib.sata.link.crc import SATACRCInserter, SATACRCChecker
 from lib.sata.link.scrambler import SATAScrambler
-from lib.sata.link.cont import SATACONTInserter
+from lib.sata.link.cont import SATACONTInserter, SATACONTRemover
 
-# Todo:
-# - RX: manage CONT
+# TODO:
+# - Test D2H
+# - Do more tests
 
 class SATALinkLayer(Module):
        def __init__(self, phy):
@@ -19,67 +20,75 @@ class SATALinkLayer(Module):
 
        # TX
                # insert CRC
-               crc = SATACRCInserter(link_layout(32))
-               self.submodules += crc
+               tx_crc = SATACRCInserter(link_layout(32))
+               self.submodules += tx_crc
 
                # scramble
-               scrambler = SATAScrambler(link_layout(32))
-               self.submodules += scrambler
+               tx_scrambler = SATAScrambler(link_layout(32))
+               self.submodules += tx_scrambler
 
                # graph
                self.comb += [
-                       Record.connect(self.sink, crc.sink),
-                       Record.connect(crc.source, scrambler.sink)
+                       Record.connect(self.sink, tx_crc.sink),
+                       Record.connect(tx_crc.source, tx_scrambler.sink)
                ]
 
                # inserter CONT and scrambled data between
                # CONT and next primitive
-               cont  = SATACONTInserter(phy_layout(32))
-               self.submodules += cont
+               tx_cont  = SATACONTInserter(phy_layout(32))
+               self.submodules += tx_cont
 
                # datas / primitives mux
                tx_insert = Signal(32)
                self.comb += [
                        If(tx_insert != 0,
-                               cont.sink.stb.eq(1),
-                               cont.sink.data.eq(tx_insert),
-                               cont.sink.charisk.eq(0x0001),
+                               tx_cont.sink.stb.eq(1),
+                               tx_cont.sink.data.eq(tx_insert),
+                               tx_cont.sink.charisk.eq(0x0001),
                        ).Elif(fsm.ongoing("H2D_COPY"),
-                               cont.sink.stb.eq(scrambler.source.stb),
-                               cont.sink.data.eq(scrambler.source.d),
-                               scrambler.source.ack.eq(cont.sink.ack),
-                               cont.sink.charisk.eq(0)
+                               tx_cont.sink.stb.eq(tx_scrambler.source.stb),
+                               tx_cont.sink.data.eq(tx_scrambler.source.d),
+                               tx_scrambler.source.ack.eq(tx_cont.sink.ack),
+                               tx_cont.sink.charisk.eq(0)
                        )
                ]
 
                # graph
-               self.comb += Record.connect(cont.source, phy.sink)
+               self.comb += Record.connect(tx_cont.source, phy.sink)
 
        # RX
+
+               # CONT remover
+               rx_cont = SATACONTRemover(phy_layout(32))
+               self.submodules += rx_cont
+
+               # graph
+               self.comb += Record.connect(phy.source, rx_cont.sink)
+
                # datas / primitives detection
                rx_det = Signal(32)
                self.comb += \
-                       If(phy.source.stb & (phy.source.charisk == 0b0001),
-                               rx_det.eq(phy.source.data)
+                       If(rx_cont.source.stb & (rx_cont.source.charisk == 0b0001),
+                               rx_det.eq(rx_cont.source.data)
                        )
 
                # descrambler
-               descrambler = SATAScrambler(link_layout(32))
-               self.submodules += descrambler
+               rx_scrambler = SATAScrambler(link_layout(32))
+               self.submodules += rx_scrambler
 
                # check CRC
-               crc_checker = SATACRCChecker(link_layout(32))
-               self.submodules += crc_checker
+               rx_crc = SATACRCChecker(link_layout(32))
+               self.submodules += rx_crc
 
                # graph
                self.comb += [
                        If(fsm.ongoing("D2H_COPY") & (rx_det == 0),
-                               descrambler.sink.stb.eq(phy.source.stb & (phy.source.charisk == 0)),
-                               descrambler.sink.d.eq(phy.source.data),
+                               rx_scrambler.sink.stb.eq(rx_cont.source.stb & (rx_cont.source.charisk == 0)),
+                               rx_scrambler.sink.d.eq(rx_cont.source.data),
                        ),
-                       phy.source.ack.eq(1),
-                       Record.connect(descrambler.source, crc_checker.sink),
-                       Record.connect(crc_checker.source, self.source)
+                       rx_cont.source.ack.eq(1),
+                       Record.connect(rx_scrambler.source, rx_crc.sink),
+                       Record.connect(rx_crc.source, self.source)
                ]
 
        # FSM
@@ -87,7 +96,7 @@ class SATALinkLayer(Module):
                        tx_insert.eq(primitives["SYNC"]),
                        If(rx_det == primitives["X_RDY"],
                                NextState("D2H_RDY")
-                       ).Elif(scrambler.source.stb & scrambler.source.sop,
+                       ).Elif(tx_scrambler.source.stb & tx_scrambler.source.sop,
                                NextState("H2D_RDY")
                        )
                )
@@ -108,9 +117,9 @@ class SATALinkLayer(Module):
                fsm.act("H2D_COPY",
                        If(rx_det == primitives["HOLD"],
                                tx_insert.eq(primitives["HOLDA"]),
-                       ).Elif(~scrambler.source.stb,
+                       ).Elif(~tx_scrambler.source.stb,
                                tx_insert.eq(primitives["HOLD"]),
-                       ).Elif(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack,
+                       ).Elif(tx_scrambler.source.stb & tx_scrambler.source.eop & tx_scrambler.source.ack,
                                NextState("H2D_EOF")
                        )
                )
index 8ec89fff80c19351b3d0f6cae7ffd81c18889b00..6847f6db4d233453b208a706a38270ed91f36a53 100644 (file)
@@ -12,6 +12,7 @@ class SATACONTInserter(Module):
                ###
 
                # Detect consecutive primitives
+               # tn insert CONT
                cnt = Signal(2)
                is_primitive = Signal()
                last_was_primitive = Signal()
@@ -46,7 +47,7 @@ class SATACONTInserter(Module):
                                )
                        )
 
-               # Repeated primitives scranbler
+               # scranbler (between CONT and next primitive)
                scrambler = Scrambler()
                self.submodules += scrambler
                self.comb += [
@@ -72,3 +73,43 @@ class SATACONTInserter(Module):
                                )
                        )
                ]
+
+class SATACONTRemover(Module):
+       def __init__(self, layout):
+               self.sink = sink = Sink(layout)
+               self.source = source = Source(layout)
+
+               ###
+
+               # Detect CONT
+               is_primitive = Signal()
+               is_cont = Signal()
+               in_cont = Signal()
+               cont_ongoing = Signal()
+
+               self.comb += [
+                       is_primitive.eq(sink.charisk != 0),
+                       is_cont.eq(is_primitive & sink.data == primitives["CONT"])
+               ]
+               self.sync += \
+                       If(is_cont,
+                               in_cont.eq(1)
+                       ).Elif(is_primitive,
+                               in_cont.eq(0)
+                       )
+               self.comb += cont_ongoing.eq(is_cont | (in_cont & ~is_primitive))
+
+               # Datapath
+               last_primitive = Signal()
+               self.sync += [
+                       If(is_primitive & ~is_cont,
+                               last_primitive.eq(sink.data)
+                       )
+               ]
+               self.comb += [
+                       Record.connect(sink, source),
+                       If(cont_ongoing,
+                               self.source.charisk.eq(0b0001),
+                               self.source.data.eq(last_primitive)
+                       )
+               ]
index 792f8f9ec310b70bad1369c19d95590d1ae0c825..66a46eb9d22d18b008c1e48738848b9ea995fc51 100644 (file)
@@ -132,6 +132,7 @@ class BFM(Module):
                print("----")
 
        def dword_callback(self, dword):
+               # CONT detection
                if dword == primitives["CONT"]:
                        self.rx_cont_ongoing = True
                elif is_primitive(dword):
@@ -148,7 +149,7 @@ class BFM(Module):
                elif dword == primitives["HOLD"]:
                        self.phy.send(primitives["HOLDA"])
 
-               # packet capture
+               # Packet capture
                elif dword == primitives["EOF"]:
                        self.rx_packet_ongoing = False
                        self.packet_callback(self.rx_packet)