1 from litesata
.common
import *
2 from litesata
.core
.link
.crc
import LiteSATACRCInserter
, LiteSATACRCChecker
3 from litesata
.core
.link
.scrambler
import LiteSATAScrambler
4 from litesata
.core
.link
.cont
import LiteSATACONTInserter
, LiteSATACONTRemover
12 class LiteSATALinkTX(Module
):
13 def __init__(self
, phy
):
14 self
.sink
= Sink(link_description(32))
15 self
.from_rx
= Sink(from_rx
)
19 self
.fsm
= fsm
= FSM(reset_state
="IDLE")
20 self
.submodules
+= fsm
23 crc
= LiteSATACRCInserter(link_description(32))
24 self
.submodules
+= crc
27 scrambler
= LiteSATAScrambler(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
= BufferizeEndpoints(LiteSATACONTInserter(phy_description(32)), "source")
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
,
68 If(self
.from_rx
.det
== primitives
["SYNC"],
75 insert
.eq(primitives
["X_RDY"]),
76 If(~self
.from_rx
.idle
,
78 ).Elif(self
.from_rx
.det
== primitives
["R_RDY"],
83 insert
.eq(primitives
["SOF"]),
89 If(self
.from_rx
.det
== primitives
["HOLD"],
90 insert
.eq(primitives
["HOLDA"]),
91 ).Elif(~scrambler
.source
.stb
,
92 insert
.eq(primitives
["HOLD"]),
93 ).Elif(scrambler
.source
.stb
& scrambler
.source
.eop
& scrambler
.source
.ack
,
98 insert
.eq(primitives
["EOF"]),
104 insert
.eq(primitives
["WTRM"]),
105 If(self
.from_rx
.det
== primitives
["R_OK"],
107 ).Elif(self
.from_rx
.det
== primitives
["R_ERR"],
112 class LiteSATALinkRX(Module
):
113 def __init__(self
, phy
):
114 self
.source
= Source(link_description(32))
116 self
.to_tx
= Source(from_rx
)
120 self
.fsm
= fsm
= FSM(reset_state
="IDLE")
121 self
.submodules
+= fsm
124 cont
= BufferizeEndpoints(LiteSATACONTRemover(phy_description(32)), "source")
125 self
.submodules
+= cont
126 self
.comb
+= Record
.connect(phy
.source
, cont
.sink
)
128 # datas / primitives detection
132 If(cont
.source
.stb
& (cont
.source
.charisk
== 0b0001),
133 det
.eq(cont
.source
.data
)
137 scrambler
= LiteSATAScrambler(link_description(32))
138 self
.submodules
+= scrambler
141 crc
= LiteSATACRCChecker(link_description(32))
142 self
.submodules
+= crc
147 If(fsm
.ongoing("IDLE"),
149 ).Elif(fsm
.ongoing("COPY"),
150 If(scrambler
.sink
.stb
& scrambler
.sink
.ack
,
154 self
.comb
+= eop
.eq(det
== primitives
["EOF"])
158 If(crc
.source
.stb
& crc
.source
.eop
& crc
.source
.ack
,
159 crc_error
.eq(crc
.source
.error
)
164 cont
.source
.ack
.eq(1),
165 Record
.connect(scrambler
.source
, crc
.sink
),
166 Record
.connect(crc
.source
, self
.source
),
168 cont_source_data_d
= Signal(32)
170 If(cont
.source
.stb
& (det
== 0),
171 scrambler
.sink
.d
.eq(cont
.source
.data
)
176 scrambler
.reset
.eq(1),
177 If(det
== primitives
["X_RDY"],
182 insert
.eq(primitives
["R_RDY"]),
183 If(det
== primitives
["SOF"],
184 NextState("WAIT_FIRST")
187 fsm
.act("WAIT_FIRST",
188 insert
.eq(primitives
["R_IP"]),
189 If(cont
.source
.stb
& (det
== 0),
194 scrambler
.sink
.sop
.eq(sop
),
195 scrambler
.sink
.eop
.eq(eop
)
198 scrambler
.sink
.stb
.eq(cont
.source
.stb
& ((det
== 0) | eop
)),
199 insert
.eq(primitives
["R_IP"]),
200 If(det
== primitives
["HOLD"],
201 insert
.eq(primitives
["HOLDA"])
202 ).Elif(det
== primitives
["EOF"],
205 insert
.eq(primitives
["HOLD"])
209 insert
.eq(primitives
["R_IP"]),
210 If(det
== primitives
["WTRM"],
215 insert
.eq(primitives
["R_IP"]),
223 insert
.eq(primitives
["R_OK"]),
224 If(det
== primitives
["SYNC"],
229 insert
.eq(primitives
["R_ERR"]),
230 If(det
== primitives
["SYNC"],
237 self
.to_tx
.idle
.eq(fsm
.ongoing("IDLE")),
238 self
.to_tx
.insert
.eq(insert
),
239 self
.to_tx
.det
.eq(det
)
242 class LiteSATALink(Module
):
243 def __init__(self
, phy
, buffer_depth
):
244 self
.submodules
.tx_buffer
= PacketBuffer(link_description(32), buffer_depth
)
245 self
.submodules
.tx
= LiteSATALinkTX(phy
)
246 self
.submodules
.rx
= LiteSATALinkRX(phy
)
247 self
.submodules
.rx_buffer
= PacketBuffer(link_description(32), buffer_depth
, almost_full
=3*buffer_depth
//4)
249 Record
.connect(self
.tx_buffer
.source
, self
.tx
.sink
),
250 Record
.connect(self
.rx
.to_tx
, self
.tx
.from_rx
),
251 Record
.connect(self
.rx
.source
, self
.rx_buffer
.sink
),
252 self
.rx
.hold
.eq(self
.rx_buffer
.almost_full
)
254 self
.sink
, self
.source
= self
.tx_buffer
.sink
, self
.rx_buffer
.source