From: Florent Kermarrec Date: Tue, 4 Nov 2014 16:35:46 +0000 (+0100) Subject: link: add SATALinkLayer skeleton (wip) X-Git-Tag: 24jan2021_ls180~2572^2~169 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=353e7fc13b9beac1a619624ad416889dd5b0041f;p=litex.git link: add SATALinkLayer skeleton (wip) --- diff --git a/lib/sata/link/__init__.py b/lib/sata/link/__init__.py new file mode 100644 index 00000000..c864be83 --- /dev/null +++ b/lib/sata/link/__init__.py @@ -0,0 +1,83 @@ +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") + ) + ) diff --git a/lib/sata/link/crc.py b/lib/sata/link/crc.py index 59c650a1..e7bb3bb0 100644 --- a/lib/sata/link/crc.py +++ b/lib/sata/link/crc.py @@ -1,5 +1,8 @@ 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 @@ -54,7 +57,7 @@ class CRCEngine(Module): # 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 @@ -104,3 +107,11 @@ class SATACRC(Module): 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 diff --git a/lib/sata/link/scrambler.py b/lib/sata/link/scrambler.py index e2aaa54b..8f301a19 100644 --- a/lib/sata/link/scrambler.py +++ b/lib/sata/link/scrambler.py @@ -3,7 +3,7 @@ from migen.genlib.misc import optree @DecorateModule(InsertReset) @DecorateModule(InsertCE) -class SATAScrambler(Module): +class Scrambler(Module): """SATA Scrambler Implement a SATA Scrambler @@ -65,3 +65,28 @@ class SATAScrambler(Module): 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) + ] diff --git a/lib/sata/std.py b/lib/sata/std.py index 3f3ea2f4..b2370c50 100644 --- a/lib/sata/std.py +++ b/lib/sata/std.py @@ -1,8 +1,29 @@ 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