merge litesata
[litex.git] / misoclib / mem / litesata / core / command / __init__.py
1 from litesata.common import *
2
3 tx_to_rx = [
4 ("write", 1),
5 ("read", 1),
6 ("identify", 1),
7 ("count", 16)
8 ]
9
10 rx_to_tx = [
11 ("dma_activate", 1),
12 ("d2h_error", 1)
13 ]
14
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)
20
21 ###
22
23 self.comb += [
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)
32 ]
33
34 dwords_counter = Counter(max=fis_max_dwords)
35 self.submodules += dwords_counter
36
37 is_write = Signal()
38 is_read = Signal()
39 is_identify = Signal()
40
41 self.fsm = fsm = FSM(reset_state="IDLE")
42 self.submodules += fsm
43 fsm.act("IDLE",
44 sink.ack.eq(0),
45 If(sink.stb & sink.sop,
46 NextState("SEND_CMD")
47 ).Else(
48 sink.ack.eq(1)
49 )
50 )
51 self.sync += \
52 If(fsm.ongoing("IDLE"),
53 is_write.eq(sink.write),
54 is_read.eq(sink.read),
55 is_identify.eq(sink.identify),
56 )
57
58 fsm.act("SEND_CMD",
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,
64 If(is_write,
65 NextState("WAIT_DMA_ACTIVATE")
66 ).Else(
67 sink.ack.eq(1),
68 NextState("IDLE")
69 )
70 )
71 )
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,
77 sink.ack.eq(1),
78 NextState("IDLE")
79 )
80 )
81 fsm.act("SEND_DATA",
82 dwords_counter.ce.eq(sink.stb & sink.ack),
83
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),
87
88 sink.ack.eq(transport.sink.ack),
89 If(sink.stb & sink.ack,
90 If(sink.eop,
91 NextState("IDLE")
92 ).Elif(dwords_counter.value == (fis_max_dwords-1),
93 NextState("WAIT_DMA_ACTIVATE")
94 )
95 )
96 )
97 self.comb += \
98 If(fsm.ongoing("SEND_DATA"),
99 transport.sink.type.eq(fis_types["DATA"]),
100 ).Else(
101 transport.sink.type.eq(fis_types["REG_H2D"]),
102 If(is_write,
103 transport.sink.command.eq(regs["WRITE_DMA_EXT"])
104 ).Elif(is_read,
105 transport.sink.command.eq(regs["READ_DMA_EXT"]),
106 ).Else(
107 transport.sink.command.eq(regs["IDENTIFY_DEVICE"]),
108 )
109 )
110 self.comb += [
111 If(sink.stb,
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)
116 )
117 ]
118
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)
124
125 ###
126
127 def test_type(name):
128 return transport.source.type == fis_types[name]
129
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
135 read_done = Signal()
136
137 self.sync += \
138 If(from_tx.read,
139 read_ndwords.eq(from_tx.count*sectors2dwords(1)-1)
140 )
141 self.comb += read_done.eq(dwords_counter.value == read_ndwords)
142
143 d2h_error = Signal()
144 clr_d2h_error = Signal()
145 set_d2h_error = Signal()
146 self.sync += \
147 If(clr_d2h_error,
148 d2h_error.eq(0)
149 ).Elif(set_d2h_error,
150 d2h_error.eq(1)
151 )
152
153 read_error = Signal()
154 clr_read_error = Signal()
155 set_read_error = Signal()
156 self.sync += \
157 If(clr_read_error,
158 read_error.eq(0)
159 ).Elif(set_read_error,
160 read_error.eq(1)
161 )
162
163 self.fsm = fsm = FSM(reset_state="IDLE")
164 self.submodules += fsm
165 fsm.act("IDLE",
166 dwords_counter.reset.eq(1),
167 transport.source.ack.eq(1),
168 clr_d2h_error.eq(1),
169 clr_read_error.eq(1),
170 If(from_tx.write,
171 NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
172 ).Elif(from_tx.read,
173 NextState("WAIT_READ_DATA_OR_REG_D2H"),
174 ).Elif(from_tx.identify,
175 NextState("WAIT_PIO_SETUP_D2H"),
176 )
177 )
178 self.sync += \
179 If(fsm.ongoing("IDLE"),
180 is_identify.eq(from_tx.identify)
181 )
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")
190 )
191 )
192 )
193 fsm.act("PRESENT_WRITE_RESPONSE",
194 source.stb.eq(1),
195 source.sop.eq(1),
196 source.eop.eq(1),
197 source.write.eq(1),
198 source.last.eq(1),
199 source.failed.eq(transport.source.error | d2h_error),
200 If(source.stb & source.ack,
201 NextState("IDLE")
202 )
203 )
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")
212 )
213 )
214 )
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")
221 )
222 )
223 )
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")
228 )
229 )
230
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),
244 If(source.eop,
245 If(is_identify,
246 NextState("IDLE")
247 ).Else(
248 NextState("WAIT_READ_DATA_OR_REG_D2H")
249 )
250 )
251 )
252 )
253
254 fsm.act("PRESENT_READ_RESPONSE",
255 source.stb.eq(1),
256 source.sop.eq(1),
257 source.eop.eq(1),
258 source.read.eq(1),
259 source.last.eq(1),
260 source.failed.eq(~read_done | read_error | d2h_error),
261 If(source.stb & source.ack,
262 NextState("IDLE")
263 )
264 )
265
266 self.comb += [
267 to_tx.dma_activate.eq(is_dma_activate),
268 to_tx.d2h_error.eq(d2h_error)
269 ]
270
271 class LiteSATACommand(Module):
272 def __init__(self, transport):
273 self.submodules.tx = LiteSATACommandTX(transport)
274 self.submodules.rx = LiteSATACommandRX(transport)
275 self.comb += [
276 self.rx.to_tx.connect(self.tx.from_rx),
277 self.tx.to_rx.connect(self.rx.from_tx)
278 ]
279 self.sink, self.source = self.tx.sink, self.rx.source