litex/lib/sata/link/__init__.py

143 lines
3.2 KiB
Python
Raw Normal View History

2014-11-04 11:35:46 -05:00
from migen.fhdl.std import *
2014-11-11 12:47:34 -05:00
from migen.genlib.fsm import FSM, NextState
2014-11-04 11:35:46 -05:00
from lib.sata.std import *
2014-11-11 12:47:34 -05:00
from lib.sata.link.crc import SATACRCInserter, SATACRCChecker
from lib.sata.link.scrambler import SATAScrambler
2014-11-04 11:35:46 -05:00
2014-11-11 06:26:32 -05:00
# Todo:
# - TX: (optional) insert COND and scramble between COND and primitives
# - RX: manage COND, HOLD from device
class SATALinkLayer(Module):
2014-11-11 12:47:34 -05:00
def __init__(self, phy):
self.sink = Sink(link_layout(32))
self.source = Source(link_layout(32))
2014-11-04 11:35:46 -05:00
2014-11-11 06:26:32 -05:00
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
2014-11-04 11:35:46 -05:00
2014-11-11 06:26:32 -05:00
# TX
# insert CRC
2014-11-11 12:47:34 -05:00
crc_inserter = SATACRCInserter(link_layout(32))
2014-11-04 11:35:46 -05:00
self.submodules += crc_inserter
2014-11-11 06:26:32 -05:00
# scramble
2014-11-11 12:47:34 -05:00
scrambler = SATAScrambler(link_layout(32))
2014-11-04 11:35:46 -05:00
self.submodules += scrambler
2014-11-11 06:26:32 -05:00
# graph
self.comb += [
Record.connect(self.sink, crc_inserter.sink),
2014-11-11 12:47:34 -05:00
Record.connect(crc_inserter.source, scrambler.sink)
2014-11-11 06:26:32 -05:00
]
2014-11-04 11:35:46 -05:00
2014-11-11 06:26:32 -05:00
# 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),
2014-11-11 12:47:34 -05:00
).Elif(fsm.ongoing("H2D_COPY"),
2014-11-11 06:26:32 -05:00
phy.sink.stb.eq(scrambler.source.stb),
2014-11-11 12:47:34 -05:00
phy.sink.data.eq(scrambler.source.d),
2014-11-11 06:26:32 -05:00
scrambler.source.ack.eq(phy.source.ack),
phy.sink.charisk.eq(0)
)
]
2014-11-04 11:35:46 -05:00
2014-11-11 06:26:32 -05:00
# 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
2014-11-11 12:47:34 -05:00
descrambler = SATAScrambler(link_layout(32))
2014-11-04 11:35:46 -05:00
self.submodules += descrambler
2014-11-11 06:26:32 -05:00
# check CRC
2014-11-11 12:47:34 -05:00
crc_checker = SATACRCChecker(link_layout(32))
2014-11-04 11:35:46 -05:00
self.submodules += crc_checker
2014-11-11 06:26:32 -05:00
# graph
self.comb += [
2014-11-11 10:15:28 -05:00
If(fsm.ongoing("H2D_COPY") & (rx_det == 0),
2014-11-11 12:47:34 -05:00
descrambler.sink.stb.eq(phy.source.stb & (phy.source.charisk == 0)),
descrambler.sink.d.eq(phy.source.data),
2014-11-11 10:15:28 -05:00
),
2014-11-11 12:47:34 -05:00
phy.source.ack.eq(1),
2014-11-11 06:26:32 -05:00
Record.connect(descrambler.source, crc_checker.sink),
Record.connect(crc_checker.source, self.source)
]
2014-11-04 11:35:46 -05:00
2014-11-11 06:26:32 -05:00
# FSM
2014-11-04 11:35:46 -05:00
fsm.act("IDLE",
2014-11-11 06:26:32 -05:00
tx_insert.eq(primitives["SYNC"]),
2014-11-11 12:47:34 -05:00
If(rx_det == primitives["X_RDY"],
2014-11-11 06:26:32 -05:00
NextState("D2H_RDY")
2014-11-11 12:47:34 -05:00
).Elif(scrambler.source.stb & scrambler.source.sop,
2014-11-11 06:26:32 -05:00
NextState("H2D_RDY")
)
2014-11-04 11:35:46 -05:00
)
2014-11-11 06:26:32 -05:00
# Host to Device
fsm.act("H2D_RDY",
tx_insert.eq(primitives["X_RDY"]),
2014-11-11 12:47:34 -05:00
If(rx_det == primitives["R_RDY"],
2014-11-11 06:26:32 -05:00
NextState("H2D_SOF")
2014-11-11 12:47:34 -05:00
)
2014-11-04 11:35:46 -05:00
)
2014-11-11 06:26:32 -05:00
fsm.act("H2D_SOF",
tx_insert.eq(primitives["SOF"]),
If(phy.sink.ack,
NextState("H2D_COPY")
)
2014-11-04 11:35:46 -05:00
)
2014-11-11 06:26:32 -05:00
fsm.act("H2D_COPY",
2014-11-11 12:47:34 -05:00
If(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack,
2014-11-11 06:26:32 -05:00
NextState("H2D_EOF")
)
2014-11-04 11:35:46 -05:00
)
2014-11-11 06:26:32 -05:00
fsm.act("H2D_EOF",
tx_insert.eq(primitives["EOF"]),
If(phy.sink.ack,
NextState("H2D_WTRM")
)
2014-11-04 11:35:46 -05:00
)
2014-11-11 06:26:32 -05:00
fsm.act("H2D_WTRM",
tx_insert.eq(primitives["WTRM"]),
2014-11-11 10:15:28 -05:00
If(rx_det == primitives["R_OK"],
2014-11-11 06:26:32 -05:00
NextState("IDLE")
).Elif(rx_det == primitives["R_ERR"],
2014-11-04 11:35:46 -05:00
NextState("IDLE")
2014-11-11 06:26:32 -05:00
)
)
# 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"]),
2014-11-11 10:15:28 -05:00
If(rx_det == primitives["SYNC"],
2014-11-04 11:35:46 -05:00
NextState("IDLE")
)
)