change submodules/specials/clock_domains syntax
[litex.git] / litesata / frontend / bist.py
1 from litesata.common import *
2 from litesata.core.link.scrambler import Scrambler
3
4 from migen.fhdl.decorators import ModuleDecorator
5 from migen.bank.description import *
6
7 class LiteSATABISTGenerator(Module):
8 def __init__(self, user_port):
9 self.start = Signal()
10 self.sector = Signal(48)
11 self.count = Signal(16)
12 self.random = Signal()
13
14 self.done = Signal()
15 self.aborted = Signal()
16 self.errors = Signal(32) # Note: Not used for writes
17
18 ###
19
20 source, sink = user_port.sink, user_port.source
21
22 counter = Counter(bits_sign=32)
23 self.submodules += counter
24
25 scrambler = scrambler = InsertReset(Scrambler())
26 self.submodules += scrambler
27 self.comb += [
28 scrambler.reset.eq(counter.reset),
29 scrambler.ce.eq(counter.ce)
30 ]
31
32 self.fsm = fsm = FSM(reset_state="IDLE")
33 self.submodules += fsm
34 fsm.act("IDLE",
35 self.done.eq(1),
36 counter.reset.eq(1),
37 If(self.start,
38 NextState("SEND_CMD_AND_DATA")
39 )
40 )
41 self.comb += [
42 source.sop.eq(counter.value == 0),
43 source.eop.eq(counter.value == (logical_sector_size//4*self.count)-1),
44 source.write.eq(1),
45 source.sector.eq(self.sector),
46 source.count.eq(self.count),
47 If(self.random,
48 source.data.eq(scrambler.value)
49 ).Else(
50 source.data.eq(counter.value)
51 )
52 ]
53 fsm.act("SEND_CMD_AND_DATA",
54 source.stb.eq(1),
55 If(source.stb & source.ack,
56 counter.ce.eq(1),
57 If(source.eop,
58 NextState("WAIT_ACK")
59 )
60 )
61 )
62 fsm.act("WAIT_ACK",
63 sink.ack.eq(1),
64 If(sink.stb,
65 NextState("IDLE")
66 )
67 )
68 self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
69
70 class LiteSATABISTChecker(Module):
71 def __init__(self, user_port):
72 self.start = Signal()
73 self.sector = Signal(48)
74 self.count = Signal(16)
75 self.random = Signal()
76
77 self.done = Signal()
78 self.aborted = Signal()
79 self.errors = Signal(32)
80
81 ###
82
83 source, sink = user_port.sink, user_port.source
84
85 counter = Counter(bits_sign=32)
86 error_counter = Counter(self.errors, bits_sign=32)
87 self.submodules += counter, error_counter
88
89 scrambler = InsertReset(Scrambler())
90 self.submodules += scrambler
91 self.comb += [
92 scrambler.reset.eq(counter.reset),
93 scrambler.ce.eq(counter.ce)
94 ]
95
96 self.fsm = fsm = FSM(reset_state="IDLE")
97 self.submodules += self.fsm
98 fsm.act("IDLE",
99 self.done.eq(1),
100 counter.reset.eq(1),
101 If(self.start,
102 error_counter.reset.eq(1),
103 NextState("SEND_CMD")
104 )
105 )
106 self.comb += [
107 source.sop.eq(1),
108 source.eop.eq(1),
109 source.read.eq(1),
110 source.sector.eq(self.sector),
111 source.count.eq(self.count),
112 ]
113 fsm.act("SEND_CMD",
114 source.stb.eq(1),
115 If(source.ack,
116 counter.reset.eq(1),
117 NextState("WAIT_ACK")
118 )
119 )
120 fsm.act("WAIT_ACK",
121 If(sink.stb & sink.read,
122 NextState("RECEIVE_DATA")
123 )
124 )
125 expected_data = Signal(32)
126 self.comb += \
127 If(self.random,
128 expected_data.eq(scrambler.value)
129 ).Else(
130 expected_data.eq(counter.value)
131 )
132 fsm.act("RECEIVE_DATA",
133 sink.ack.eq(1),
134 If(sink.stb,
135 counter.ce.eq(1),
136 If(sink.data != expected_data,
137 error_counter.ce.eq(~sink.last)
138 ),
139 If(sink.eop,
140 If(sink.last,
141 NextState("IDLE")
142 ).Else(
143 NextState("WAIT_ACK")
144 )
145 )
146 )
147 )
148 self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
149
150 class LiteSATABISTUnitCSR(Module, AutoCSR):
151 def __init__(self, bist_unit):
152 self._start = CSR()
153 self._sector = CSRStorage(48)
154 self._count = CSRStorage(16)
155 self._loops = CSRStorage(8)
156 self._random = CSRStorage()
157
158 self._done = CSRStatus()
159 self._aborted = CSRStatus()
160 self._errors = CSRStatus(32)
161 self._cycles = CSRStatus(32)
162
163 ###
164
165 self.submodules += bist_unit
166
167 start = self._start.r & self._start.re
168 done = self._done.status
169 loops = self._loops.storage
170
171 self.comb += [
172 bist_unit.sector.eq(self._sector.storage),
173 bist_unit.count.eq(self._count.storage),
174 bist_unit.random.eq(self._random.storage),
175
176 self._aborted.status.eq(bist_unit.aborted),
177 self._errors.status.eq(bist_unit.errors)
178 ]
179
180 self.fsm = fsm = FSM(reset_state="IDLE")
181 loop_counter = Counter(bits_sign=8)
182 self.submodules += fsm, loop_counter
183 fsm.act("IDLE",
184 self._done.status.eq(1),
185 loop_counter.reset.eq(1),
186 If(start,
187 NextState("CHECK")
188 )
189 )
190 fsm.act("CHECK",
191 If(loop_counter.value < loops,
192 NextState("START")
193 ).Else(
194 NextState("IDLE")
195 )
196 )
197 fsm.act("START",
198 bist_unit.start.eq(1),
199 NextState("WAIT_DONE")
200 )
201 fsm.act("WAIT_DONE",
202 If(bist_unit.done,
203 loop_counter.ce.eq(1),
204 NextState("CHECK")
205 )
206 )
207
208 cycles_counter = Counter(self._cycles.status)
209 self.submodules += cycles_counter
210 self.sync += [
211 cycles_counter.reset.eq(start),
212 cycles_counter.ce.eq(~fsm.ongoing("IDLE"))
213 ]
214
215 class LiteSATABISTIdentify(Module):
216 def __init__(self, user_port):
217 self.start = Signal()
218 self.done = Signal()
219
220 fifo = SyncFIFO([("data", 32)], 512, buffered=True)
221 self.submodules += fifo
222 self.source = fifo.source
223
224 ###
225
226 source, sink = user_port.sink, user_port.source
227
228 self.fsm = fsm = FSM(reset_state="IDLE")
229 fsm.act("IDLE",
230 self.done.eq(1),
231 If(self.start,
232 NextState("SEND_CMD")
233 )
234 )
235 self.comb += [
236 source.sop.eq(1),
237 source.eop.eq(1),
238 source.identify.eq(1),
239 ]
240 fsm.act("SEND_CMD",
241 source.stb.eq(1),
242 If(source.stb & source.ack,
243 NextState("WAIT_ACK")
244 )
245 )
246 fsm.act("WAIT_ACK",
247 If(sink.stb & sink.identify,
248 NextState("RECEIVE_DATA")
249 )
250 )
251 self.comb += fifo.sink.data.eq(sink.data)
252 fsm.act("RECEIVE_DATA",
253 sink.ack.eq(fifo.sink.ack),
254 If(sink.stb,
255 fifo.sink.stb.eq(1),
256 If(sink.eop,
257 NextState("IDLE")
258 )
259 )
260 )
261
262 class LiteSATABISTIdentifyCSR(Module, AutoCSR):
263 def __init__(self, bist_identify):
264 self._start = CSR()
265 self._done = CSRStatus()
266 self._source_stb = CSRStatus()
267 self._source_ack = CSR()
268 self._source_data = CSRStatus(32)
269
270 ###
271
272 self.submodules += bist_identify
273 self.comb += [
274 bist_identify.start.eq(self._start.r & self._start.re),
275 self._done.status.eq(bist_identify.done),
276
277 self._source_stb.status.eq(bist_identify.source.stb),
278 self._source_data.status.eq(bist_identify.source.data),
279 bist_identify.source.ack.eq(self._source_ack.r & self._source_ack.re)
280 ]
281
282 class LiteSATABIST(Module, AutoCSR):
283 def __init__(self, crossbar, with_csr=False):
284 generator = LiteSATABISTGenerator(crossbar.get_port())
285 checker = LiteSATABISTChecker(crossbar.get_port())
286 identify = LiteSATABISTIdentify(crossbar.get_port())
287 if with_csr:
288 generator = LiteSATABISTUnitCSR(generator)
289 checker = LiteSATABISTUnitCSR(checker)
290 identify = LiteSATABISTIdentifyCSR(identify)
291 self.submodules += generator, checker, identify