link: manage CONT on RX path

This commit is contained in:
Florent Kermarrec 2014-12-03 11:50:31 +01:00
parent 47a5a9529b
commit d3974882e4
3 changed files with 86 additions and 35 deletions

View file

@ -4,10 +4,11 @@ from migen.genlib.fsm import FSM, NextState
from lib.sata.std import * from lib.sata.std import *
from lib.sata.link.crc import SATACRCInserter, SATACRCChecker from lib.sata.link.crc import SATACRCInserter, SATACRCChecker
from lib.sata.link.scrambler import SATAScrambler from lib.sata.link.scrambler import SATAScrambler
from lib.sata.link.cont import SATACONTInserter from lib.sata.link.cont import SATACONTInserter, SATACONTRemover
# Todo: # TODO:
# - RX: manage CONT # - Test D2H
# - Do more tests
class SATALinkLayer(Module): class SATALinkLayer(Module):
def __init__(self, phy): def __init__(self, phy):
@ -19,67 +20,75 @@ class SATALinkLayer(Module):
# TX # TX
# insert CRC # insert CRC
crc = SATACRCInserter(link_layout(32)) tx_crc = SATACRCInserter(link_layout(32))
self.submodules += crc self.submodules += tx_crc
# scramble # scramble
scrambler = SATAScrambler(link_layout(32)) tx_scrambler = SATAScrambler(link_layout(32))
self.submodules += scrambler self.submodules += tx_scrambler
# graph # graph
self.comb += [ self.comb += [
Record.connect(self.sink, crc.sink), Record.connect(self.sink, tx_crc.sink),
Record.connect(crc.source, scrambler.sink) Record.connect(tx_crc.source, tx_scrambler.sink)
] ]
# inserter CONT and scrambled data between # inserter CONT and scrambled data between
# CONT and next primitive # CONT and next primitive
cont = SATACONTInserter(phy_layout(32)) tx_cont = SATACONTInserter(phy_layout(32))
self.submodules += cont self.submodules += tx_cont
# datas / primitives mux # datas / primitives mux
tx_insert = Signal(32) tx_insert = Signal(32)
self.comb += [ self.comb += [
If(tx_insert != 0, If(tx_insert != 0,
cont.sink.stb.eq(1), tx_cont.sink.stb.eq(1),
cont.sink.data.eq(tx_insert), tx_cont.sink.data.eq(tx_insert),
cont.sink.charisk.eq(0x0001), tx_cont.sink.charisk.eq(0x0001),
).Elif(fsm.ongoing("H2D_COPY"), ).Elif(fsm.ongoing("H2D_COPY"),
cont.sink.stb.eq(scrambler.source.stb), tx_cont.sink.stb.eq(tx_scrambler.source.stb),
cont.sink.data.eq(scrambler.source.d), tx_cont.sink.data.eq(tx_scrambler.source.d),
scrambler.source.ack.eq(cont.sink.ack), tx_scrambler.source.ack.eq(tx_cont.sink.ack),
cont.sink.charisk.eq(0) tx_cont.sink.charisk.eq(0)
) )
] ]
# graph # graph
self.comb += Record.connect(cont.source, phy.sink) self.comb += Record.connect(tx_cont.source, phy.sink)
# RX # RX
# CONT remover
rx_cont = SATACONTRemover(phy_layout(32))
self.submodules += rx_cont
# graph
self.comb += Record.connect(phy.source, rx_cont.sink)
# datas / primitives detection # datas / primitives detection
rx_det = Signal(32) rx_det = Signal(32)
self.comb += \ self.comb += \
If(phy.source.stb & (phy.source.charisk == 0b0001), If(rx_cont.source.stb & (rx_cont.source.charisk == 0b0001),
rx_det.eq(phy.source.data) rx_det.eq(rx_cont.source.data)
) )
# descrambler # descrambler
descrambler = SATAScrambler(link_layout(32)) rx_scrambler = SATAScrambler(link_layout(32))
self.submodules += descrambler self.submodules += rx_scrambler
# check CRC # check CRC
crc_checker = SATACRCChecker(link_layout(32)) rx_crc = SATACRCChecker(link_layout(32))
self.submodules += crc_checker self.submodules += rx_crc
# graph # graph
self.comb += [ self.comb += [
If(fsm.ongoing("D2H_COPY") & (rx_det == 0), If(fsm.ongoing("D2H_COPY") & (rx_det == 0),
descrambler.sink.stb.eq(phy.source.stb & (phy.source.charisk == 0)), rx_scrambler.sink.stb.eq(rx_cont.source.stb & (rx_cont.source.charisk == 0)),
descrambler.sink.d.eq(phy.source.data), rx_scrambler.sink.d.eq(rx_cont.source.data),
), ),
phy.source.ack.eq(1), rx_cont.source.ack.eq(1),
Record.connect(descrambler.source, crc_checker.sink), Record.connect(rx_scrambler.source, rx_crc.sink),
Record.connect(crc_checker.source, self.source) Record.connect(rx_crc.source, self.source)
] ]
# FSM # FSM
@ -87,7 +96,7 @@ class SATALinkLayer(Module):
tx_insert.eq(primitives["SYNC"]), tx_insert.eq(primitives["SYNC"]),
If(rx_det == primitives["X_RDY"], If(rx_det == primitives["X_RDY"],
NextState("D2H_RDY") NextState("D2H_RDY")
).Elif(scrambler.source.stb & scrambler.source.sop, ).Elif(tx_scrambler.source.stb & tx_scrambler.source.sop,
NextState("H2D_RDY") NextState("H2D_RDY")
) )
) )
@ -108,9 +117,9 @@ class SATALinkLayer(Module):
fsm.act("H2D_COPY", fsm.act("H2D_COPY",
If(rx_det == primitives["HOLD"], If(rx_det == primitives["HOLD"],
tx_insert.eq(primitives["HOLDA"]), tx_insert.eq(primitives["HOLDA"]),
).Elif(~scrambler.source.stb, ).Elif(~tx_scrambler.source.stb,
tx_insert.eq(primitives["HOLD"]), tx_insert.eq(primitives["HOLD"]),
).Elif(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack, ).Elif(tx_scrambler.source.stb & tx_scrambler.source.eop & tx_scrambler.source.ack,
NextState("H2D_EOF") NextState("H2D_EOF")
) )
) )

View file

@ -12,6 +12,7 @@ class SATACONTInserter(Module):
### ###
# Detect consecutive primitives # Detect consecutive primitives
# tn insert CONT
cnt = Signal(2) cnt = Signal(2)
is_primitive = Signal() is_primitive = Signal()
last_was_primitive = Signal() last_was_primitive = Signal()
@ -46,7 +47,7 @@ class SATACONTInserter(Module):
) )
) )
# Repeated primitives scranbler # scranbler (between CONT and next primitive)
scrambler = Scrambler() scrambler = Scrambler()
self.submodules += scrambler self.submodules += scrambler
self.comb += [ self.comb += [
@ -72,3 +73,43 @@ class SATACONTInserter(Module):
) )
) )
] ]
class SATACONTRemover(Module):
def __init__(self, layout):
self.sink = sink = Sink(layout)
self.source = source = Source(layout)
###
# Detect CONT
is_primitive = Signal()
is_cont = Signal()
in_cont = Signal()
cont_ongoing = Signal()
self.comb += [
is_primitive.eq(sink.charisk != 0),
is_cont.eq(is_primitive & sink.data == primitives["CONT"])
]
self.sync += \
If(is_cont,
in_cont.eq(1)
).Elif(is_primitive,
in_cont.eq(0)
)
self.comb += cont_ongoing.eq(is_cont | (in_cont & ~is_primitive))
# Datapath
last_primitive = Signal()
self.sync += [
If(is_primitive & ~is_cont,
last_primitive.eq(sink.data)
)
]
self.comb += [
Record.connect(sink, source),
If(cont_ongoing,
self.source.charisk.eq(0b0001),
self.source.data.eq(last_primitive)
)
]

View file

@ -132,6 +132,7 @@ class BFM(Module):
print("----") print("----")
def dword_callback(self, dword): def dword_callback(self, dword):
# CONT detection
if dword == primitives["CONT"]: if dword == primitives["CONT"]:
self.rx_cont_ongoing = True self.rx_cont_ongoing = True
elif is_primitive(dword): elif is_primitive(dword):
@ -148,7 +149,7 @@ class BFM(Module):
elif dword == primitives["HOLD"]: elif dword == primitives["HOLD"]:
self.phy.send(primitives["HOLDA"]) self.phy.send(primitives["HOLDA"])
# packet capture # Packet capture
elif dword == primitives["EOF"]: elif dword == primitives["EOF"]:
self.rx_packet_ongoing = False self.rx_packet_ongoing = False
self.packet_callback(self.rx_packet) self.packet_callback(self.rx_packet)