--- /dev/null
+from migen.fhdl.std import *
+
+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
+
+class SATALinkLayer(Module):
+ def __init__(self, phy, dw=32):
+ self.submodules.tx = SATALinkLayerTX(dw)
+ self.submodules.rx = SATALinkLayerRX(dw)
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ phy.sink.stb.eq(1),
+ phy.sink.d.eq(SYNC_VAL),
+ NextState("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")
+ )
+ fsm.act("SOF",
+ phy.sink.stb.eq(1),
+ phy.sink.d.eq(SOF_VAL),
+ NextState("COPY")
+ )
+ fsm.act("COPY",
+ phy.sink.stb.eq(1),
+ phy.sink.d.eq(),
+ NextState("EOF")
+ )
+ fsm.act("EOF",
+ phy.sink.stb.eq(1),
+ phy.sink.d.eq(EOF_VAL),
+ NextState("")
+ )
+ 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),
+ NextState("IDLE")
+ ).Elif(phy.source.stb & (phy.source.d == R_ERR_VAL),
+ NextState("IDLE")
+ )
+ )
from migen.fhdl.std import *
from migen.genlib.misc import optree
+from migen.actorlib.crc import CRCInserter, CRCChecker
+
+from lib.sata.std import *
class CRCEngine(Module):
"""Cyclic Redundancy Check Engine
# compute and optimize CRC's LFSR
curval = [[("new", i)] for i in range(width)]
for i in range(width):
- feedback = curval.pop()
+ feedback = curval.pop()
for j in range(width-1):
if (polynom & (1<<(j+1))):
curval[j] += feedback
self.value.eq(reg_i),
self.error.eq(self.engine.next != self.check)
]
+
+class SATACRCInserter(CRCInserter):
+ def __init__(self, layout):
+ CRCInserter.__init__(self, SATACRC, layout)
+
+class SATACRCChecker(CRCChecker):
+ def __init__(self, layout):
+ CRCChecker.__init__(self, SATACRC, layout)
\ No newline at end of file
@DecorateModule(InsertReset)
@DecorateModule(InsertCE)
-class SATAScrambler(Module):
+class Scrambler(Module):
"""SATA Scrambler
Implement a SATA Scrambler
self.comb += next_value[n].eq(optree("^", eq))
self.comb += self.value.eq(next_value)
+
+class SATAScrambler(Module):
+ def __init__(self, layout):
+ self.sink = sink = Sink(layout)
+ self.source = source = Source(layout)
+
+ ###
+
+ self.submodules.scrambler = Scrambler()
+ ongoing = Signal()
+ self.sync += [
+ If(sink.stb & sink.ack,
+ If(sink.eop,
+ ongoing.eq(0)
+ ).Elsif(sink.sop,
+ ongoing.eq(1)
+ )
+ )
+ ]
+ self.comb += [
+ self.scrambler.ce.eq(sink.stb & (sink.sop | ongoing)),
+ self.scrambler.reset.eq(~ongoing),
+ Record.connect(sink, source),
+ source.d.eq(sink.d ^ self.scrambler.value)
+ ]
from migen.fhdl.std import *
+ALIGN_VAL = 0x7B4A4ABC
+SYNC_VAL = 0xB5B5957C
+R_RDY_VAL = 0x4A4A957C
+R_OK_VAL = 0x3535B57C
+R_ERR_VAL = 0x5656B57C
+R_IP_VAL = 0X5555B57C
+X_RDY_VAL = 0x5757B57C
+CONT_VAL = 0x9999AA7C
+WTRM_VAL = 0x5858B57C
+SOF_VAL = 0x3737B57C
+EOF_VAL = 0xD5D5B57C
+HOLD_VAL = 0xD5D5AA7C
+HOLD_ACK = 0X9595AA7C
+
def phy_layout(dw):
layout = [
("p_packetized", True),
("d", dw)
]
return layout
+
+def link_layout(dw):
+ layout = [
+ ("p_packetized", True),
+ ("d", dw)
+ ]
+ return layout