link: SATALinkLayer skeleton
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 11 Nov 2014 11:26:32 +0000 (12:26 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 11 Nov 2014 11:29:37 +0000 (12:29 +0100)
lib/sata/link/__init__.py

index c864be831101a7097c8f713045f83266fda7dab9..972c99a88ead54c23c452b76280ff421c914f849 100644 (file)
@@ -4,80 +4,136 @@ from lib.sata.std import *
 from lib.sata.link import crc
 from lib.sata.link import scrambler
 
-class SATALinkLayerTX(Module):
-       def __init__(self, dw):
+# Todo:
+# - TX: (optional) insert COND and scramble between COND and primitives
+# - RX: manage COND, HOLD from device
+
+class SATALinkLayer(Module):
+       def __init__(self, phy, dw=32):
                self.sink = Sink(link_layout(dw))
-               self.source = Source(phy_layout(dw))
+               self.source = Source(link_layout(dw))
 
-               ###
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
 
-       # insert CRC
+       # TX
+               # insert CRC
                crc_inserter = crc.SATACRCInserter(link_layout(dw))
                self.submodules += crc_inserter
 
-       # scramble
+               # scramble
                scrambler = scrambler.SATAScrambler(link_layout(dw))
                self.submodules += scrambler
 
-class SATALinkLayerRX(Module):
-       def __init__(self, dw):
-               self.sink = Sink(link_layout(dw))
-               self.source = Source(phy_layout(dw))
+               # graph
+               self.comb += [
+                       Record.connect(self.sink, crc_inserter.sink),
+                       Record.connect(crc_inserter, scrambler)
+               ]
 
-               ###
+               # datas / primitives mux
+               tx_insert = Signal(32)
+               self.comb += [
+                       If(tx_insert != 0,
+                               phy.sink.stb.eq(1),
+                               phy.sink.data.eq(tx_insert),
+                               phy.sink.charisk.eq(0x0001),
+                       ).Elsif(fsm.ongoing("H2D_COPY"),
+                               phy.sink.stb.eq(scrambler.source.stb),
+                               phy.sink.data.eq(scrambler.source.data),
+                               scrambler.source.ack.eq(phy.source.ack),
+                               phy.sink.charisk.eq(0)
+                       )
+               ]
 
-       # descramble
+       # RX
+               # datas / primitives detection
+               rx_det = Signal(32)
+               self.comb += \
+                       If(phy.source.stb & (phy.source.charisk == 0b0001),
+                               rx_det.eq(phy.source.data)
+                       )
+
+               # descrambler
                descrambler = descrambler.SATAScrambler(link_layout(dw))
                self.submodules += descrambler
 
-       # check CRC
+               # check CRC
                crc_checker = crc.SATACRCChecker(link_layout(dw))
                self.submodules += crc_checker
 
-class SATALinkLayer(Module):
-       def __init__(self, phy, dw=32):
-               self.submodules.tx = SATALinkLayerTX(dw)
-               self.submodules.rx = SATALinkLayerRX(dw)
+               # graph
+               self.comb += [
+                       If(fsm.ongoing("H2D_COPY" & (rx_det == 0),
+                               descrambler.sink.stb.eq(phy.source.stb & (phy.charisk == 0)),
+                               descrambler.sink.d.eq(phy.source.d),
+                       )
+                       Record.connect(descrambler.source, crc_checker.sink),
+                       Record.connect(crc_checker.source, self.source)
+               ]
 
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += fsm
+       # FSM
                fsm.act("IDLE",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(SYNC_VAL),
-                       NextState("RDY")
-               )
-               fsm.act("RDY",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(X_RDY_VAL)
-                       If(phy.source.stb & (phy.source.d == X_RDY_VAL),
-                               NextState("SOF")
+                       tx_insert.eq(primitives["SYNC"]),
+                       If(rx_primitive == "X_RDY",
+                               NextState("D2H_RDY")
+                       ).Elif(scrambler.stb & scrambler.sop,
+                               NextState("H2D_RDY")
+                       )
                )
-               fsm.act("SOF",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(SOF_VAL),
-                       NextState("COPY")
+
+               # Host to Device
+               fsm.act("H2D_RDY",
+                       tx_insert.eq(primitives["X_RDY"]),
+                       If(rx_primitive == primitives["R_RDY"]),
+                               NextState("H2D_SOF")
                )
-               fsm.act("COPY",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(),
-                       NextState("EOF")
+               fsm.act("H2D_SOF",
+                       tx_insert.eq(primitives["SOF"]),
+                       If(phy.sink.ack,
+                               NextState("H2D_COPY")
+                       )
                )
-               fsm.act("EOF",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(EOF_VAL),
-                       NextState("")
+               fsm.act("H2D_COPY",
+                       If(scrambler.stb & scrambler.ack & scramvbler.eop,
+                               NextState("H2D_EOF")
+                       )
                )
-               fsm.act("EOF",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(EOF_VAL),
-                       NextState("")
+               fsm.act("H2D_EOF",
+                       tx_insert.eq(primitives["EOF"]),
+                       If(phy.sink.ack,
+                               NextState("H2D_WTRM")
+                       )
                )
-               fsm.act("WTRM",
-                       phy.sink.stb.eq(1),
-                       phy.sink.d.eq(WTRM_VAL),
-                       If(phy.source.stb & (phy.source.d == R_OK_VAL),
+               fsm.act("H2D_WTRM",
+                       tx_insert.eq(primitives["WTRM"]),
+                       If(rx_det == primitives["R_OK"]),
+                               NextState("IDLE")
+                       ).Elif(rx_det == primitives["R_ERR"],
                                NextState("IDLE")
-                       ).Elif(phy.source.stb & (phy.source.d == R_ERR_VAL),
+                       )
+               )
+
+               # Device to Host
+               fsm.act("D2H_RDY",
+                       tx_insert.eq(primitives["R_RDY"]),
+                       If(rx_det == primitives["SOF"],
+                               NextState("D2H_COPY")
+                       )
+               )
+               fsm.act("D2H_COPY",
+                       If(rx_det == primitives["EOF"],
+                               NextState("D2H_WTRM")
+                       )
+               )
+               fsm.act("D2H_EOF",
+                       If(rx_det == primitives["WTRM"],
+                               NextState("D2H_WTRM")
+                       )
+               )
+               fsm.act("D2H_WTRM",
+                       tx_insert.eq(primitives["R_OK"]),
+                       If(rx_det == primitives["SYNC"]),
                                NextState("IDLE")
                        )
                )