link: split SATALinkLayer in SATALinkLayerTX and SATALinkLayerRX

This commit is contained in:
Florent Kermarrec 2014-12-03 15:29:01 +01:00
parent d3974882e4
commit ddd4b65f44
2 changed files with 136 additions and 103 deletions

View file

View file

@ -7,159 +7,192 @@ from lib.sata.link.scrambler import SATAScrambler
from lib.sata.link.cont import SATACONTInserter, SATACONTRemover
# TODO:
# - Test D2H
# - Do more tests
class SATALinkLayer(Module):
from_rx = [
("idle", 1),
("insert", 32),
("det", 32)
]
class SATALinkLayerTX(Module):
def __init__(self, phy):
self.sink = Sink(link_layout(32))
self.source = Source(link_layout(32))
self.from_rx = Sink(from_rx)
###
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
# TX
# insert CRC
tx_crc = SATACRCInserter(link_layout(32))
self.submodules += tx_crc
crc = SATACRCInserter(link_layout(32))
self.submodules += crc
# scramble
tx_scrambler = SATAScrambler(link_layout(32))
self.submodules += tx_scrambler
scrambler = SATAScrambler(link_layout(32))
self.submodules += scrambler
# graph
# connect CRC / scrambler
self.comb += [
Record.connect(self.sink, tx_crc.sink),
Record.connect(tx_crc.source, tx_scrambler.sink)
Record.connect(self.sink, crc.sink),
Record.connect(crc.source, scrambler.sink)
]
# inserter CONT and scrambled data between
# CONT and next primitive
tx_cont = SATACONTInserter(phy_layout(32))
self.submodules += tx_cont
cont = SATACONTInserter(phy_layout(32))
self.submodules += cont
# datas / primitives mux
tx_insert = Signal(32)
insert = Signal(32)
self.comb += [
If(tx_insert != 0,
tx_cont.sink.stb.eq(1),
tx_cont.sink.data.eq(tx_insert),
tx_cont.sink.charisk.eq(0x0001),
).Elif(fsm.ongoing("H2D_COPY"),
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)
If(self.from_rx.insert,
cont.sink.stb.eq(1),
cont.sink.data.eq(self.from_rx.insert),
cont.sink.charisk.eq(0x0001),
).
Elif(insert,
cont.sink.stb.eq(1),
cont.sink.data.eq(insert),
cont.sink.charisk.eq(0x0001),
).Elif(fsm.ongoing("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)
)
]
self.comb += Record.connect(cont.source, phy.sink)
# graph
self.comb += Record.connect(tx_cont.source, phy.sink)
# FSM
fsm.act("IDLE",
insert.eq(primitives["SYNC"]),
If(scrambler.source.stb & scrambler.source.sop,
If(self.from_rx.idle,
NextState("RDY")
)
)
)
fsm.act("RDY",
insert.eq(primitives["X_RDY"]),
If(self.from_rx.det == primitives["R_RDY"],
NextState("SOF")
)
)
fsm.act("SOF",
insert.eq(primitives["SOF"]),
If(phy.sink.ack,
NextState("COPY")
)
)
fsm.act("COPY",
If(self.from_rx.det == primitives["HOLD"],
insert.eq(primitives["HOLDA"]),
).Elif(~scrambler.source.stb,
insert.eq(primitives["HOLD"]),
).Elif(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack,
NextState("EOF")
)
)
fsm.act("EOF",
insert.eq(primitives["EOF"]),
If(phy.sink.ack,
NextState("WTRM")
)
)
fsm.act("WTRM",
insert.eq(primitives["WTRM"]),
If(self.from_rx.det == primitives["R_OK"],
NextState("IDLE")
).Elif(self.from_rx.det == primitives["R_ERR"],
NextState("IDLE")
)
)
# RX
class SATALinkLayerRX(Module):
def __init__(self, phy):
self.source = Source(link_layout(32))
self.to_tx = Source(from_rx)
###
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
# CONT remover
rx_cont = SATACONTRemover(phy_layout(32))
self.submodules += rx_cont
# graph
self.comb += Record.connect(phy.source, rx_cont.sink)
cont = SATACONTRemover(phy_layout(32))
self.submodules += cont
self.comb += Record.connect(phy.source, cont.sink)
# datas / primitives detection
rx_det = Signal(32)
insert = Signal(32)
det = Signal(32)
self.comb += \
If(rx_cont.source.stb & (rx_cont.source.charisk == 0b0001),
rx_det.eq(rx_cont.source.data)
If(cont.source.stb & (cont.source.charisk == 0b0001),
det.eq(cont.source.data)
)
# descrambler
rx_scrambler = SATAScrambler(link_layout(32))
self.submodules += rx_scrambler
scrambler = SATAScrambler(link_layout(32))
self.submodules += scrambler
# check CRC
rx_crc = SATACRCChecker(link_layout(32))
self.submodules += rx_crc
crc = SATACRCChecker(link_layout(32))
self.submodules += crc
# graph
self.comb += [
If(fsm.ongoing("D2H_COPY") & (rx_det == 0),
rx_scrambler.sink.stb.eq(rx_cont.source.stb & (rx_cont.source.charisk == 0)),
rx_scrambler.sink.d.eq(rx_cont.source.data),
If(fsm.ongoing("COPY") & (det == 0),
scrambler.sink.stb.eq(cont.source.stb & (cont.source.charisk == 0)),
scrambler.sink.d.eq(cont.source.data),
),
rx_cont.source.ack.eq(1),
Record.connect(rx_scrambler.source, rx_crc.sink),
Record.connect(rx_crc.source, self.source)
cont.source.ack.eq(1),
Record.connect(scrambler.source, crc.sink),
Record.connect(crc.source, self.source)
]
# FSM
# FSM
fsm.act("IDLE",
tx_insert.eq(primitives["SYNC"]),
If(rx_det == primitives["X_RDY"],
NextState("D2H_RDY")
).Elif(tx_scrambler.source.stb & tx_scrambler.source.sop,
NextState("H2D_RDY")
If(det == primitives["X_RDY"],
NextState("RDY")
)
)
# Host to Device
fsm.act("H2D_RDY",
tx_insert.eq(primitives["X_RDY"]),
If(rx_det == primitives["R_RDY"],
NextState("H2D_SOF")
fsm.act("RDY",
insert.eq(primitives["R_RDY"]),
If(det == primitives["SOF"],
NextState("COPY")
)
)
fsm.act("H2D_SOF",
tx_insert.eq(primitives["SOF"]),
If(phy.sink.ack,
NextState("H2D_COPY")
fsm.act("COPY",
If(det == primitives["HOLD"],
insert.eq(primitives["HOLDA"])
).Elif(det == primitives["EOF"],
NextState("WTRM")
)
)
fsm.act("H2D_COPY",
If(rx_det == primitives["HOLD"],
tx_insert.eq(primitives["HOLDA"]),
).Elif(~tx_scrambler.source.stb,
tx_insert.eq(primitives["HOLD"]),
).Elif(tx_scrambler.source.stb & tx_scrambler.source.eop & tx_scrambler.source.ack,
NextState("H2D_EOF")
fsm.act("EOF",
If(det == primitives["WTRM"],
NextState("WTRM")
)
)
fsm.act("H2D_EOF",
tx_insert.eq(primitives["EOF"]),
If(phy.sink.ack,
NextState("H2D_WTRM")
)
)
fsm.act("H2D_WTRM",
tx_insert.eq(primitives["WTRM"]),
If(rx_det == primitives["R_OK"],
NextState("IDLE")
).Elif(rx_det == primitives["R_ERR"],
fsm.act("WTRM",
insert.eq(primitives["R_OK"]),
If(det == primitives["SYNC"],
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["HOLD"],
tx_insert.eq(primitives["HOLDA"])
).Elif(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")
)
)
# to TX
self.comb += [
self.to_tx.idle.eq(fsm.ongoing("IDLE")),
self.to_tx.insert.eq(insert),
self.to_tx.det.eq(det)
]
class SATALinkLayer(Module):
def __init__(self, phy):
self.submodules.tx = SATALinkLayerTX(phy)
self.submodules.rx = SATALinkLayerRX(phy)
self.comb += Record.connect(self.rx.to_tx, self.tx.from_rx)
self.sink, self.source = self.tx.sink, self.rx.source