1 from litesata
.common
import *
15 class LiteSATACommandTX(Module
):
16 def __init__(self
, transport
):
17 self
.sink
= sink
= Sink(command_tx_description(32))
18 self
.to_rx
= to_rx
= Source(tx_to_rx
)
19 self
.from_rx
= from_rx
= Sink(rx_to_tx
)
24 transport
.sink
.pm_port
.eq(0),
25 transport
.sink
.features
.eq(0),
26 transport
.sink
.lba
.eq(sink
.sector
),
27 transport
.sink
.device
.eq(0xe0),
28 transport
.sink
.count
.eq(sink
.count
),
29 transport
.sink
.icc
.eq(0),
30 transport
.sink
.control
.eq(0),
31 transport
.sink
.data
.eq(sink
.data
)
34 dwords_counter
= Counter(max=fis_max_dwords
)
35 self
.submodules
+= dwords_counter
39 is_identify
= Signal()
41 self
.fsm
= fsm
= FSM(reset_state
="IDLE")
42 self
.submodules
+= fsm
45 If(sink
.stb
& sink
.sop
,
52 If(fsm
.ongoing("IDLE"),
53 is_write
.eq(sink
.write
),
54 is_read
.eq(sink
.read
),
55 is_identify
.eq(sink
.identify
),
59 transport
.sink
.stb
.eq(sink
.stb
),
60 transport
.sink
.sop
.eq(1),
61 transport
.sink
.eop
.eq(1),
62 transport
.sink
.c
.eq(1),
63 If(transport
.sink
.stb
& transport
.sink
.ack
,
65 NextState("WAIT_DMA_ACTIVATE")
72 fsm
.act("WAIT_DMA_ACTIVATE",
73 dwords_counter
.reset
.eq(1),
74 If(from_rx
.dma_activate
,
75 NextState("SEND_DATA")
76 ).Elif(from_rx
.d2h_error
,
82 dwords_counter
.ce
.eq(sink
.stb
& sink
.ack
),
84 transport
.sink
.stb
.eq(sink
.stb
),
85 transport
.sink
.sop
.eq(dwords_counter
.value
== 0),
86 transport
.sink
.eop
.eq((dwords_counter
.value
== (fis_max_dwords
-1)) | sink
.eop
),
88 sink
.ack
.eq(transport
.sink
.ack
),
89 If(sink
.stb
& sink
.ack
,
92 ).Elif(dwords_counter
.value
== (fis_max_dwords
-1),
93 NextState("WAIT_DMA_ACTIVATE")
98 If(fsm
.ongoing("SEND_DATA"),
99 transport
.sink
.type.eq(fis_types
["DATA"]),
101 transport
.sink
.type.eq(fis_types
["REG_H2D"]),
103 transport
.sink
.command
.eq(regs
["WRITE_DMA_EXT"])
105 transport
.sink
.command
.eq(regs
["READ_DMA_EXT"]),
107 transport
.sink
.command
.eq(regs
["IDENTIFY_DEVICE"]),
112 to_rx
.write
.eq(sink
.write
),
113 to_rx
.read
.eq(sink
.read
),
114 to_rx
.identify
.eq(sink
.identify
),
115 to_rx
.count
.eq(sink
.count
)
119 class LiteSATACommandRX(Module
):
120 def __init__(self
, transport
):
121 self
.source
= source
= Source(command_rx_description(32))
122 self
.to_tx
= to_tx
= Source(rx_to_tx
)
123 self
.from_tx
= from_tx
= Sink(tx_to_rx
)
128 return transport
.source
.type == fis_types
[name
]
130 is_identify
= Signal()
131 is_dma_activate
= Signal()
132 read_ndwords
= Signal(max=sectors2dwords(2**16))
133 dwords_counter
= Counter(max=sectors2dwords(2**16))
134 self
.submodules
+= dwords_counter
139 read_ndwords
.eq(from_tx
.count
*sectors2dwords(1)-1)
141 self
.comb
+= read_done
.eq(dwords_counter
.value
== read_ndwords
)
144 clr_d2h_error
= Signal()
145 set_d2h_error
= Signal()
149 ).Elif(set_d2h_error
,
153 read_error
= Signal()
154 clr_read_error
= Signal()
155 set_read_error
= Signal()
159 ).Elif(set_read_error
,
163 self
.fsm
= fsm
= FSM(reset_state
="IDLE")
164 self
.submodules
+= fsm
166 dwords_counter
.reset
.eq(1),
167 transport
.source
.ack
.eq(1),
169 clr_read_error
.eq(1),
171 NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
173 NextState("WAIT_READ_DATA_OR_REG_D2H"),
174 ).Elif(from_tx
.identify
,
175 NextState("WAIT_PIO_SETUP_D2H"),
179 If(fsm
.ongoing("IDLE"),
180 is_identify
.eq(from_tx
.identify
)
182 fsm
.act("WAIT_WRITE_ACTIVATE_OR_REG_D2H",
183 transport
.source
.ack
.eq(1),
184 If(transport
.source
.stb
,
185 If(test_type("DMA_ACTIVATE_D2H"),
186 is_dma_activate
.eq(1),
187 ).Elif(test_type("REG_D2H"),
188 set_d2h_error
.eq(transport
.source
.status
[reg_d2h_status
["err"]]),
189 NextState("PRESENT_WRITE_RESPONSE")
193 fsm
.act("PRESENT_WRITE_RESPONSE",
199 source
.failed
.eq(transport
.source
.error | d2h_error
),
200 If(source
.stb
& source
.ack
,
204 fsm
.act("WAIT_READ_DATA_OR_REG_D2H",
205 transport
.source
.ack
.eq(1),
206 If(transport
.source
.stb
,
207 transport
.source
.ack
.eq(0),
208 If(test_type("DATA"),
209 NextState("PRESENT_READ_DATA")
210 ).Elif(test_type("REG_D2H"),
211 NextState("PRESENT_READ_RESPONSE")
215 fsm
.act("WAIT_PIO_SETUP_D2H",
216 transport
.source
.ack
.eq(1),
217 If(transport
.source
.stb
,
218 transport
.source
.ack
.eq(0),
219 If(test_type("PIO_SETUP_D2H"),
220 NextState("PRESENT_PIO_SETUP_D2H")
224 fsm
.act("PRESENT_PIO_SETUP_D2H",
225 transport
.source
.ack
.eq(1),
226 If(transport
.source
.stb
& transport
.source
.eop
,
227 NextState("WAIT_READ_DATA_OR_REG_D2H")
231 fsm
.act("PRESENT_READ_DATA",
232 set_read_error
.eq(transport
.source
.error
),
233 source
.stb
.eq(transport
.source
.stb
),
234 source
.sop
.eq(transport
.source
.sop
),
235 source
.eop
.eq(transport
.source
.eop
),
236 source
.read
.eq(~is_identify
),
237 source
.identify
.eq(is_identify
),
238 source
.failed
.eq(transport
.source
.error
),
239 source
.last
.eq(is_identify
),
240 source
.data
.eq(transport
.source
.data
),
241 transport
.source
.ack
.eq(source
.ack
),
242 If(source
.stb
& source
.ack
,
243 dwords_counter
.ce
.eq(~read_done
),
248 NextState("WAIT_READ_DATA_OR_REG_D2H")
254 fsm
.act("PRESENT_READ_RESPONSE",
260 source
.failed
.eq(~read_done | read_error | d2h_error
),
261 If(source
.stb
& source
.ack
,
267 to_tx
.dma_activate
.eq(is_dma_activate
),
268 to_tx
.d2h_error
.eq(d2h_error
)
271 class LiteSATACommand(Module
):
272 def __init__(self
, transport
):
273 self
.submodules
.tx
= LiteSATACommandTX(transport
)
274 self
.submodules
.rx
= LiteSATACommandRX(transport
)
276 self
.rx
.to_tx
.connect(self
.tx
.from_rx
),
277 self
.tx
.to_rx
.connect(self
.rx
.from_tx
)
279 self
.sink
, self
.source
= self
.tx
.sink
, self
.rx
.source