1 from liteeth
.common
import *
3 class LiteEthMACCRCEngine(Module
):
4 """Cyclic Redundancy Check Engine
6 Compute next CRC value from last CRC value and data input using
7 an optimized asynchronous LFSR.
12 Width of the data bus.
16 Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
27 def __init__(self
, data_width
, width
, polynom
):
28 self
.data
= Signal(data_width
)
29 self
.last
= Signal(width
)
30 self
.next
= Signal(width
)
36 Replace even numbers of XORs in the equation
37 with an equivalent XOR
46 for key
, value
in d
.items():
51 # compute and optimize CRC's LFSR
52 curval
= [[("state", i
)] for i
in range(width
)]
53 for i
in range(data_width
):
54 feedback
= curval
.pop() + [("din", i
)]
55 for j
in range(width
-1):
56 if (polynom
& (1<<(j
+1))):
58 curval
[j
] = _optimize_eq(curval
[j
])
59 curval
.insert(0, feedback
)
62 for i
in range(width
):
64 for t
, n
in curval
[i
]:
66 xors
+= [self
.last
[n
]]
68 xors
+= [self
.data
[n
]]
69 self
.comb
+= self
.next
[i
].eq(optree("^", xors
))
71 @DecorateModule(InsertReset
)
72 @DecorateModule(InsertCE
)
73 class LiteEthMACCRC32(Module
):
76 Implement an IEEE 802.3 CRC generator/checker.
81 Width of the data bus.
88 CRC value (used for generator).
90 CRC error (used for checker).
96 def __init__(self
, data_width
):
97 self
.data
= Signal(data_width
)
98 self
.value
= Signal(self
.width
)
103 self
.submodules
.engine
= LiteEthMACCRCEngine(data_width
, self
.width
, self
.polynom
)
104 reg
= Signal(self
.width
, reset
=self
.init
)
105 self
.sync
+= reg
.eq(self
.engine
.next
)
107 self
.engine
.data
.eq(self
.data
),
108 self
.engine
.last
.eq(reg
),
110 self
.value
.eq(~reg
[::-1]),
111 self
.error
.eq(self
.engine
.next
!= self
.check
)
114 class LiteEthMACCRCInserter(Module
):
117 Append a CRC at the end of each packet.
121 description : description
122 description of the dataflow.
127 Packets input without CRC.
129 Packets output with CRC.
131 def __init__(self
, crc_class
, description
):
132 self
.sink
= sink
= Sink(description
)
133 self
.source
= source
= Source(description
)
140 fsm
= FSM(reset_state
="IDLE")
141 self
.submodules
+= crc
, fsm
146 If(sink
.stb
& sink
.sop
,
152 crc
.ce
.eq(sink
.stb
& source
.ack
),
153 crc
.data
.eq(sink
.data
),
154 Record
.connect(sink
, source
),
156 If(sink
.stb
& sink
.eop
& source
.ack
,
160 ratio
= crc
.width
//dw
162 cnt
= Signal(max=ratio
, reset
=ratio
-1)
166 chooser(crc
.value
, cnt
, source
.data
, reverse
=True),
169 If(source
.ack
, NextState("IDLE"))
172 self
.comb
+= cnt_done
.eq(cnt
== 0)
174 If(fsm
.ongoing("IDLE"),
176 ).Elif(fsm
.ongoing("INSERT") & ~cnt_done
,
177 cnt
.eq(cnt
- source
.ack
)
183 source
.data
.eq(crc
.value
),
184 If(source
.ack
, NextState("IDLE"))
186 self
.comb
+= self
.busy
.eq(~fsm
.ongoing("IDLE"))
188 class LiteEthMACCRC32Inserter(LiteEthMACCRCInserter
):
189 def __init__(self
, description
):
190 LiteEthMACCRCInserter
.__init
__(self
, LiteEthMACCRC32
, description
)
192 class LiteEthMACCRCChecker(Module
):
195 Check CRC at the end of each packet.
199 description : description
200 description of the dataflow.
205 Packets input with CRC.
207 Packets output without CRC and "error" set to 0
208 on eop when CRC OK / set to 1 when CRC KO.
210 def __init__(self
, crc_class
, description
):
211 self
.sink
= sink
= Sink(description
)
212 self
.source
= source
= Source(description
)
219 self
.submodules
+= crc
220 ratio
= crc
.width
//dw
223 fifo
= InsertReset(SyncFIFO(description
, ratio
+ 1))
224 self
.submodules
+= fifo
226 fsm
= FSM(reset_state
="RESET")
227 self
.submodules
+= fsm
234 fifo_full
.eq(fifo
.fifo
.level
== ratio
),
235 fifo_in
.eq(sink
.stb
& (~fifo_full | fifo_out
)),
236 fifo_out
.eq(source
.stb
& source
.ack
),
238 Record
.connect(sink
, fifo
.sink
),
239 fifo
.sink
.stb
.eq(fifo_in
),
240 self
.sink
.ack
.eq(fifo_in
),
242 source
.stb
.eq(sink
.stb
& fifo_full
),
243 source
.sop
.eq(fifo
.source
.sop
),
244 source
.eop
.eq(sink
.eop
),
245 fifo
.source
.ack
.eq(fifo_out
),
246 source
.payload
.eq(fifo
.source
.payload
),
248 source
.error
.eq(sink
.error | crc
.error
),
257 crc
.data
.eq(sink
.data
),
258 If(sink
.stb
& sink
.sop
& sink
.ack
,
264 crc
.data
.eq(sink
.data
),
265 If(sink
.stb
& sink
.ack
,
272 self
.comb
+= self
.busy
.eq(~fsm
.ongoing("IDLE"))
274 class LiteEthMACCRC32Checker(LiteEthMACCRCChecker
):
275 def __init__(self
, description
):
276 LiteEthMACCRCChecker
.__init
__(self
, LiteEthMACCRC32
, description
)