9e57017aa23b6eb9cb4a44b3bae1e29995ee976b
1 from collections
import OrderedDict
2 from migen
.fhdl
.std
import *
3 from migen
.genlib
.fsm
import FSM
, NextState
4 from migen
.genlib
.record
import *
5 from migen
.genlib
.misc
import chooser
, optree
6 from migen
.flow
.actor
import Sink
, Source
7 from migen
.actorlib
.fifo
import SyncFIFO
9 from misoclib
.com
.liteusb
.common
import *
12 class CRCEngine(Module
):
13 """Cyclic Redundancy Check Engine
15 Compute next CRC value from last CRC value and data input using
16 an optimized asynchronous LFSR.
21 Width of the data bus.
25 Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
36 def __init__(self
, dat_width
, width
, polynom
):
37 self
.data
= Signal(dat_width
)
38 self
.last
= Signal(width
)
39 self
.next
= Signal(width
)
45 Replace even numbers of XORs in the equation
46 with an equivalent XOR
55 for key
, value
in d
.items():
60 # compute and optimize CRC's LFSR
61 curval
= [[("state", i
)] for i
in range(width
)]
62 for i
in range(dat_width
):
63 feedback
= curval
.pop() + [("din", i
)]
64 for j
in range(width
-1):
65 if (polynom
& (1<<(j
+1))):
67 curval
[j
] = _optimize_eq(curval
[j
])
68 curval
.insert(0, feedback
)
71 for i
in range(width
):
73 for t
, n
in curval
[i
]:
75 xors
+= [self
.last
[n
]]
77 xors
+= [self
.data
[n
]]
78 self
.comb
+= self
.next
[i
].eq(optree("^", xors
))
81 @DecorateModule(InsertReset
)
82 @DecorateModule(InsertCE
)
86 Implement an IEEE 802.3 CRC generator/checker.
91 Width of the data bus.
98 CRC value (used for generator).
100 CRC error (used for checker).
107 def __init__(self
, dat_width
):
108 self
.data
= Signal(dat_width
)
109 self
.value
= Signal(self
.width
)
110 self
.error
= Signal()
114 self
.submodules
.engine
= CRCEngine(dat_width
, self
.width
, self
.polynom
)
115 reg
= Signal(self
.width
, reset
=self
.init
)
116 self
.sync
+= reg
.eq(self
.engine
.next
)
118 self
.engine
.data
.eq(self
.data
),
119 self
.engine
.last
.eq(reg
),
121 self
.value
.eq(~reg
[::-1]),
122 self
.error
.eq(self
.engine
.next
!= self
.check
)
126 class CRCInserter(Module
):
129 Append a CRC at the end of each packet.
134 Layout of the dataflow.
139 Packets input without CRC.
141 Packets output with CRC.
143 def __init__(self
, crc_class
, layout
):
144 self
.sink
= sink
= Sink(layout
)
145 self
.source
= source
= Source(layout
)
152 fsm
= FSM(reset_state
="IDLE")
153 self
.submodules
+= crc
, fsm
158 If(sink
.stb
& sink
.sop
,
164 crc
.ce
.eq(sink
.stb
& source
.ack
),
165 crc
.data
.eq(sink
.data
),
166 Record
.connect(sink
, source
),
168 If(sink
.stb
& sink
.eop
& source
.ack
,
172 ratio
= crc
.width
//dw
174 cnt
= Signal(max=ratio
, reset
=ratio
-1)
178 chooser(crc
.value
, cnt
, source
.data
, reverse
=True),
181 If(source
.ack
, NextState("IDLE"))
184 self
.comb
+= cnt_done
.eq(cnt
== 0)
186 If(fsm
.ongoing("IDLE"),
188 ).Elif(fsm
.ongoing("INSERT") & ~cnt_done
,
189 cnt
.eq(cnt
- source
.ack
)
195 source
.data
.eq(crc
.value
),
196 If(source
.ack
, NextState("IDLE"))
198 self
.comb
+= self
.busy
.eq(~fsm
.ongoing("IDLE"))
201 class LiteUSBCRC32Inserter(CRCInserter
):
203 CRCInserter
.__init
__(self
, CRC32
, user_description(8))
206 class CRCChecker(Module
):
209 Check CRC at the end of each packet.
214 Layout of the dataflow.
219 Packets input with CRC.
221 Packets output without CRC and "error" set to 0
222 on eop when CRC OK / set to 1 when CRC KO.
224 def __init__(self
, crc_class
, layout
):
225 self
.sink
= sink
= Sink(layout
)
226 self
.source
= source
= Source(layout
)
233 self
.submodules
+= crc
234 ratio
= crc
.width
//dw
237 fifo
= InsertReset(SyncFIFO(layout
, ratio
+ 1))
238 self
.submodules
+= fifo
240 fsm
= FSM(reset_state
="RESET")
241 self
.submodules
+= fsm
248 fifo_full
.eq(fifo
.fifo
.level
== ratio
),
249 fifo_in
.eq(sink
.stb
& (~fifo_full | fifo_out
)),
250 fifo_out
.eq(source
.stb
& source
.ack
),
252 Record
.connect(sink
, fifo
.sink
),
253 fifo
.sink
.stb
.eq(fifo_in
),
254 self
.sink
.ack
.eq(fifo_in
),
256 source
.stb
.eq(sink
.stb
& fifo_full
),
257 source
.sop
.eq(fifo
.source
.sop
),
258 source
.eop
.eq(sink
.eop
),
259 fifo
.source
.ack
.eq(fifo_out
),
260 source
.payload
.eq(fifo
.source
.payload
),
262 source
.error
.eq(sink
.error | crc
.error
),
271 crc
.data
.eq(sink
.data
),
272 If(sink
.stb
& sink
.sop
& sink
.ack
,
278 crc
.data
.eq(sink
.data
),
279 If(sink
.stb
& sink
.ack
,
286 self
.comb
+= self
.busy
.eq(~fsm
.ongoing("IDLE"))
289 class LiteUSBCRC32Checker(CRCChecker
):
291 CRCChecker
.__init
__(self
, CRC32
, user_description(8))