1 from collections
import OrderedDict
2 from functools
import reduce
3 from operator
import xor
6 from migen
.genlib
.misc
import chooser
8 from misoc
.interconnect
.stream
import *
11 class LiteEthMACCRCEngine(Module
):
12 """Cyclic Redundancy Check Engine
14 Compute next CRC value from last CRC value and data input using
15 an optimized asynchronous LFSR.
20 Width of the data bus.
24 Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
35 def __init__(self
, data_width
, width
, polynom
):
36 self
.data
= Signal(data_width
)
37 self
.last
= Signal(width
)
38 self
.next
= Signal(width
)
44 Replace even numbers of XORs in the equation
45 with an equivalent XOR
54 for key
, value
in d
.items():
59 # compute and optimize CRC's LFSR
60 curval
= [[("state", i
)] for i
in range(width
)]
61 for i
in range(data_width
):
62 feedback
= curval
.pop() + [("din", i
)]
63 for j
in range(width
-1):
64 if (polynom
& (1<<(j
+1))):
66 curval
[j
] = _optimize_eq(curval
[j
])
67 curval
.insert(0, feedback
)
70 for i
in range(width
):
72 for t
, n
in curval
[i
]:
74 xors
+= [self
.last
[n
]]
76 xors
+= [self
.data
[n
]]
77 self
.comb
+= self
.next
[i
].eq(reduce(xor
, xors
))
82 class LiteEthMACCRC32(Module
):
85 Implement an IEEE 802.3 CRC generator/checker.
90 Width of the data bus.
97 CRC value (used for generator).
99 CRC error (used for checker).
105 def __init__(self
, data_width
):
106 self
.data
= Signal(data_width
)
107 self
.value
= Signal(self
.width
)
108 self
.error
= Signal()
112 self
.submodules
.engine
= LiteEthMACCRCEngine(data_width
, self
.width
, self
.polynom
)
113 reg
= Signal(self
.width
, reset
=self
.init
)
114 self
.sync
+= reg
.eq(self
.engine
.next
)
116 self
.engine
.data
.eq(self
.data
),
117 self
.engine
.last
.eq(reg
),
119 self
.value
.eq(~reg
[::-1]),
120 self
.error
.eq(self
.engine
.next
!= self
.check
)
124 class LiteEthMACCRCInserter(Module
):
127 Append a CRC at the end of each packet.
131 description : description
132 description of the dataflow.
137 Packets input without CRC.
139 Packets output with CRC.
141 def __init__(self
, crc_class
, description
):
142 self
.sink
= sink
= Sink(description
)
143 self
.source
= source
= Source(description
)
150 fsm
= FSM(reset_state
="IDLE")
151 self
.submodules
+= crc
, fsm
156 If(sink
.stb
& sink
.sop
,
162 crc
.ce
.eq(sink
.stb
& source
.ack
),
163 crc
.data
.eq(sink
.data
),
164 Record
.connect(sink
, source
),
166 If(sink
.stb
& sink
.eop
& source
.ack
,
170 ratio
= crc
.width
//dw
172 cnt
= Signal(max=ratio
, reset
=ratio
-1)
176 chooser(crc
.value
, cnt
, source
.data
, reverse
=True),
179 If(source
.ack
, NextState("IDLE"))
182 self
.comb
+= cnt_done
.eq(cnt
== 0)
184 If(fsm
.ongoing("IDLE"),
186 ).Elif(fsm
.ongoing("INSERT") & ~cnt_done
,
187 cnt
.eq(cnt
- source
.ack
)
193 source
.data
.eq(crc
.value
),
194 If(source
.ack
, NextState("IDLE"))
196 self
.comb
+= self
.busy
.eq(~fsm
.ongoing("IDLE"))
199 class LiteEthMACCRC32Inserter(LiteEthMACCRCInserter
):
200 def __init__(self
, description
):
201 LiteEthMACCRCInserter
.__init
__(self
, LiteEthMACCRC32
, description
)
204 class LiteEthMACCRCChecker(Module
):
207 Check CRC at the end of each packet.
211 description : description
212 description of the dataflow.
217 Packets input with CRC.
219 Packets output without CRC and "error" set to 0
220 on eop when CRC OK / set to 1 when CRC KO.
222 def __init__(self
, crc_class
, description
):
223 self
.sink
= sink
= Sink(description
)
224 self
.source
= source
= Source(description
)
231 self
.submodules
+= crc
232 ratio
= crc
.width
//dw
234 fifo
= ResetInserter()(SyncFIFO(description
, ratio
+ 1))
235 self
.submodules
+= fifo
237 fsm
= FSM(reset_state
="RESET")
238 self
.submodules
+= fsm
245 fifo_full
.eq(fifo
.fifo
.level
== ratio
),
246 fifo_in
.eq(sink
.stb
& (~fifo_full | fifo_out
)),
247 fifo_out
.eq(source
.stb
& source
.ack
),
249 Record
.connect(sink
, fifo
.sink
),
250 fifo
.sink
.stb
.eq(fifo_in
),
251 self
.sink
.ack
.eq(fifo_in
),
253 source
.stb
.eq(sink
.stb
& fifo_full
),
254 source
.sop
.eq(fifo
.source
.sop
),
255 source
.eop
.eq(sink
.eop
),
256 fifo
.source
.ack
.eq(fifo_out
),
257 source
.payload
.eq(fifo
.source
.payload
),
259 source
.error
.eq(sink
.error | crc
.error
),
267 self
.comb
+= crc
.data
.eq(sink
.data
)
269 If(sink
.stb
& sink
.sop
& sink
.ack
,
275 If(sink
.stb
& sink
.ack
,
282 self
.comb
+= self
.busy
.eq(~fsm
.ongoing("IDLE"))
285 class LiteEthMACCRC32Checker(LiteEthMACCRCChecker
):
286 def __init__(self
, description
):
287 LiteEthMACCRCChecker
.__init
__(self
, LiteEthMACCRC32
, description
)