diff --git a/lib/sata/link/__init__.py b/lib/sata/link/__init__.py index c864be831..972c99a88 100644 --- a/lib/sata/link/__init__.py +++ b/lib/sata/link/__init__.py @@ -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): - self.sink = Sink(link_layout(dw)) - self.source = Source(phy_layout(dw)) - - ### - - # insert CRC - crc_inserter = crc.SATACRCInserter(link_layout(dw)) - self.submodules += crc_inserter - - # 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)) - - ### - - # descramble - descrambler = descrambler.SATAScrambler(link_layout(dw)) - self.submodules += descrambler - - # check CRC - crc_checker = crc.SATACRCChecker(link_layout(dw)) - self.submodules += crc_checker +# 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.submodules.tx = SATALinkLayerTX(dw) - self.submodules.rx = SATALinkLayerRX(dw) + self.sink = Sink(link_layout(dw)) + self.source = Source(link_layout(dw)) fsm = FSM(reset_state="IDLE") self.submodules += fsm + + # TX + # insert CRC + crc_inserter = crc.SATACRCInserter(link_layout(dw)) + self.submodules += crc_inserter + + # scramble + scrambler = scrambler.SATAScrambler(link_layout(dw)) + self.submodules += scrambler + + # 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) + ) + ] + + # 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 + crc_checker = crc.SATACRCChecker(link_layout(dw)) + self.submodules += crc_checker + + # 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.act("IDLE", - phy.sink.stb.eq(1), - phy.sink.d.eq(SYNC_VAL), - NextState("RDY") + tx_insert.eq(primitives["SYNC"]), + If(rx_primitive == "X_RDY", + NextState("D2H_RDY") + ).Elif(scrambler.stb & scrambler.sop, + NextState("H2D_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") + + # Host to Device + fsm.act("H2D_RDY", + tx_insert.eq(primitives["X_RDY"]), + If(rx_primitive == primitives["R_RDY"]), + NextState("H2D_SOF") ) - fsm.act("SOF", - phy.sink.stb.eq(1), - phy.sink.d.eq(SOF_VAL), - NextState("COPY") + fsm.act("H2D_SOF", + tx_insert.eq(primitives["SOF"]), + If(phy.sink.ack, + NextState("H2D_COPY") + ) ) - fsm.act("COPY", - phy.sink.stb.eq(1), - phy.sink.d.eq(), - NextState("EOF") + 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("EOF", - phy.sink.stb.eq(1), - phy.sink.d.eq(EOF_VAL), - NextState("") - ) - 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(phy.source.stb & (phy.source.d == R_ERR_VAL), + ).Elif(rx_det == primitives["R_ERR"], + NextState("IDLE") + ) + ) + + # 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") ) )