link: SATALinkLayer skeleton
This commit is contained in:
parent
294855e292
commit
67aaf09b53
|
@ -4,80 +4,136 @@ from lib.sata.std import *
|
||||||
from lib.sata.link import crc
|
from lib.sata.link import crc
|
||||||
from lib.sata.link import scrambler
|
from lib.sata.link import scrambler
|
||||||
|
|
||||||
class SATALinkLayerTX(Module):
|
# Todo:
|
||||||
def __init__(self, dw):
|
# - TX: (optional) insert COND and scramble between COND and primitives
|
||||||
self.sink = Sink(link_layout(dw))
|
# - RX: manage COND, HOLD from device
|
||||||
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
|
|
||||||
|
|
||||||
class SATALinkLayer(Module):
|
class SATALinkLayer(Module):
|
||||||
def __init__(self, phy, dw=32):
|
def __init__(self, phy, dw=32):
|
||||||
self.submodules.tx = SATALinkLayerTX(dw)
|
self.sink = Sink(link_layout(dw))
|
||||||
self.submodules.rx = SATALinkLayerRX(dw)
|
self.source = Source(link_layout(dw))
|
||||||
|
|
||||||
fsm = FSM(reset_state="IDLE")
|
fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += fsm
|
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",
|
fsm.act("IDLE",
|
||||||
phy.sink.stb.eq(1),
|
tx_insert.eq(primitives["SYNC"]),
|
||||||
phy.sink.d.eq(SYNC_VAL),
|
If(rx_primitive == "X_RDY",
|
||||||
NextState("RDY")
|
NextState("D2H_RDY")
|
||||||
|
).Elif(scrambler.stb & scrambler.sop,
|
||||||
|
NextState("H2D_RDY")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
fsm.act("RDY",
|
|
||||||
phy.sink.stb.eq(1),
|
# Host to Device
|
||||||
phy.sink.d.eq(X_RDY_VAL)
|
fsm.act("H2D_RDY",
|
||||||
If(phy.source.stb & (phy.source.d == X_RDY_VAL),
|
tx_insert.eq(primitives["X_RDY"]),
|
||||||
NextState("SOF")
|
If(rx_primitive == primitives["R_RDY"]),
|
||||||
|
NextState("H2D_SOF")
|
||||||
)
|
)
|
||||||
fsm.act("SOF",
|
fsm.act("H2D_SOF",
|
||||||
phy.sink.stb.eq(1),
|
tx_insert.eq(primitives["SOF"]),
|
||||||
phy.sink.d.eq(SOF_VAL),
|
If(phy.sink.ack,
|
||||||
NextState("COPY")
|
NextState("H2D_COPY")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
fsm.act("COPY",
|
fsm.act("H2D_COPY",
|
||||||
phy.sink.stb.eq(1),
|
If(scrambler.stb & scrambler.ack & scramvbler.eop,
|
||||||
phy.sink.d.eq(),
|
NextState("H2D_EOF")
|
||||||
NextState("EOF")
|
)
|
||||||
)
|
)
|
||||||
fsm.act("EOF",
|
fsm.act("H2D_EOF",
|
||||||
phy.sink.stb.eq(1),
|
tx_insert.eq(primitives["EOF"]),
|
||||||
phy.sink.d.eq(EOF_VAL),
|
If(phy.sink.ack,
|
||||||
NextState("")
|
NextState("H2D_WTRM")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
fsm.act("EOF",
|
fsm.act("H2D_WTRM",
|
||||||
phy.sink.stb.eq(1),
|
tx_insert.eq(primitives["WTRM"]),
|
||||||
phy.sink.d.eq(EOF_VAL),
|
If(rx_det == primitives["R_OK"]),
|
||||||
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),
|
|
||||||
NextState("IDLE")
|
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")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue