1 from lib
.sata
.common
import *
2 from lib
.sata
.link
.crc
import SATACRCInserter
, SATACRCChecker
3 from lib
.sata
.link
.scrambler
import SATAScrambler
4 from lib
.sata
.link
.cont
import SATACONTInserter
, SATACONTRemover
12 class SATALinkTX(Module
):
13 def __init__(self
, phy
):
14 self
.sink
= Sink(link_description(32))
15 self
.from_rx
= Sink(from_rx
)
19 fsm
= FSM(reset_state
="IDLE")
20 self
.submodules
+= fsm
23 crc
= SATACRCInserter(link_description(32))
24 self
.submodules
+= crc
27 scrambler
= SATAScrambler(link_description(32))
28 self
.submodules
+= scrambler
30 # connect CRC / scrambler
32 Record
.connect(self
.sink
, crc
.sink
),
33 Record
.connect(crc
.source
, scrambler
.sink
)
36 # inserter CONT and scrambled data between
37 # CONT and next primitive
38 cont
= SATACONTInserter(phy_description(32))
39 self
.submodules
+= cont
41 # datas / primitives mux
44 If(self
.from_rx
.insert
,
46 cont
.sink
.data
.eq(self
.from_rx
.insert
),
47 cont
.sink
.charisk
.eq(0x0001),
51 cont
.sink
.data
.eq(insert
),
52 cont
.sink
.charisk
.eq(0x0001),
53 ).Elif(fsm
.ongoing("COPY"),
54 cont
.sink
.stb
.eq(scrambler
.source
.stb
),
55 cont
.sink
.data
.eq(scrambler
.source
.d
),
56 scrambler
.source
.ack
.eq(cont
.sink
.ack
),
57 cont
.sink
.charisk
.eq(0)
60 self
.comb
+= Record
.connect(cont
.source
, phy
.sink
)
64 scrambler
.reset
.eq(1),
66 insert
.eq(primitives
["SYNC"]),
67 If(scrambler
.source
.stb
& scrambler
.source
.sop
,
73 insert
.eq(primitives
["X_RDY"]),
74 If(~self
.from_rx
.idle
,
76 ).Elif(self
.from_rx
.det
== primitives
["R_RDY"],
81 insert
.eq(primitives
["SOF"]),
87 If(self
.from_rx
.det
== primitives
["HOLD"],
88 insert
.eq(primitives
["HOLDA"]),
89 ).Elif(~scrambler
.source
.stb
,
90 insert
.eq(primitives
["HOLD"]),
91 ).Elif(scrambler
.source
.stb
& scrambler
.source
.eop
& scrambler
.source
.ack
,
96 insert
.eq(primitives
["EOF"]),
102 insert
.eq(primitives
["WTRM"]),
103 If(self
.from_rx
.det
== primitives
["R_OK"],
105 ).Elif(self
.from_rx
.det
== primitives
["R_ERR"],
110 class SATALinkRX(Module
):
111 def __init__(self
, phy
):
112 self
.source
= Source(link_description(32))
113 self
.to_tx
= Source(from_rx
)
117 fsm
= FSM(reset_state
="IDLE")
118 self
.submodules
+= fsm
121 cont
= SATACONTRemover(phy_description(32))
122 self
.submodules
+= cont
123 self
.comb
+= Record
.connect(phy
.source
, cont
.sink
)
125 # datas / primitives detection
129 If(cont
.source
.stb
& (cont
.source
.charisk
== 0b0001),
130 det
.eq(cont
.source
.data
)
134 scrambler
= SATAScrambler(link_description(32))
135 self
.submodules
+= scrambler
138 crc
= SATACRCChecker(link_description(32))
139 self
.submodules
+= crc
143 If(fsm
.ongoing("RDY"),
145 ).Elif(scrambler
.sink
.stb
& scrambler
.sink
.ack
,
149 # small fifo to manage HOLD
150 self
.submodules
.fifo
= SyncFIFO(link_description(32), 32)
154 If(fsm
.ongoing("COPY") & (det
== 0),
155 scrambler
.sink
.stb
.eq(cont
.source
.stb
& (cont
.source
.charisk
== 0)),
156 scrambler
.sink
.d
.eq(cont
.source
.data
),
158 scrambler
.sink
.stb
.eq(0)
161 scrambler
.sink
.sop
.eq(sop
),
162 scrambler
.sink
.eop
.eq(det
== primitives
["EOF"]),
163 cont
.source
.ack
.eq(1),
164 Record
.connect(scrambler
.source
, crc
.sink
),
165 Record
.connect(crc
.source
, self
.fifo
.sink
),
166 Record
.connect(self
.fifo
.source
, self
.source
)
171 scrambler
.reset
.eq(1),
172 If(det
== primitives
["X_RDY"],
177 insert
.eq(primitives
["R_RDY"]),
178 If(det
== primitives
["SOF"],
183 insert
.eq(primitives
["R_IP"]),
184 If(det
== primitives
["HOLD"],
185 insert
.eq(primitives
["HOLDA"])
186 ).Elif(det
== primitives
["EOF"],
188 ).Elif(self
.fifo
.fifo
.level
> 8,
189 insert
.eq(primitives
["HOLD"])
193 If(det
== primitives
["WTRM"],
198 insert
.eq(primitives
["R_OK"]),
199 If(det
== primitives
["SYNC"],
206 self
.to_tx
.idle
.eq(fsm
.ongoing("IDLE")),
207 self
.to_tx
.insert
.eq(insert
),
208 self
.to_tx
.det
.eq(det
)
211 class SATALink(Module
):
212 def __init__(self
, phy
):
213 self
.submodules
.tx
= SATALinkTX(phy
)
214 self
.submodules
.rx
= SATALinkRX(phy
)
215 self
.comb
+= Record
.connect(self
.rx
.to_tx
, self
.tx
.from_rx
)
216 self
.sink
, self
.source
= self
.tx
.sink
, self
.rx
.source