litex/litesata/core/link/crc.py

116 lines
2.4 KiB
Python
Raw Normal View History

from collections import OrderedDict
2015-01-16 17:52:41 -05:00
from litesata.common import *
2014-11-04 11:35:46 -05:00
from migen.actorlib.crc import CRCInserter, CRCChecker
2014-11-03 12:54:41 -05:00
class CRCEngine(Module):
"""Cyclic Redundancy Check Engine
Compute next CRC value from last CRC value and data input using
an optimized asynchronous LFSR.
Parameters
----------
width : int
Width of the data bus and CRC.
polynom : int
Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
Attributes
----------
d : in
Data input.
last : in
last CRC value.
next :
next CRC value.
"""
def __init__(self, width, polynom):
self.d = Signal(width)
self.last = Signal(width)
self.next = Signal(width)
###
def _optimize_eq(l):
"""
Replace even numbers of XORs in the equation
with an equivalent XOR
"""
d = OrderedDict()
2014-11-03 12:54:41 -05:00
for e in l:
if e in d:
d[e] += 1
else:
d[e] = 1
r = []
for key, value in d.items():
if value%2 != 0:
r.append(key)
return r
new = Signal(32)
self.comb += new.eq(self.last ^ self.d)
# compute and optimize CRC's LFSR
curval = [[("new", i)] for i in range(width)]
for i in range(width):
2014-11-04 11:35:46 -05:00
feedback = curval.pop()
2014-11-04 05:40:43 -05:00
for j in range(width-1):
if (polynom & (1<<(j+1))):
2014-11-03 12:54:41 -05:00
curval[j] += feedback
curval[j] = _optimize_eq(curval[j])
2014-11-04 05:40:43 -05:00
curval.insert(0, feedback)
2014-11-03 12:54:41 -05:00
# implement logic
for i in range(width):
xors = []
for t, n in curval[i]:
if t == "new":
xors += [new[n]]
self.comb += self.next[i].eq(optree("^", xors))
@DecorateModule(InsertReset)
@DecorateModule(InsertCE)
2015-01-16 17:52:41 -05:00
class LiteSATACRC(Module):
2014-11-03 12:54:41 -05:00
"""SATA CRC
Implement a SATA CRC generator/checker
Attributes
----------
value : out
CRC value (used for generator).
error : out
CRC error (used for checker).
"""
width = 32
polynom = 0x04C11DB7
init = 0x52325032
2014-12-25 07:11:22 -05:00
check = 0x00000000
def __init__(self, dw=32):
2014-11-03 12:54:41 -05:00
self.d = Signal(self.width)
self.value = Signal(self.width)
self.error = Signal()
###
self.engine = CRCEngine(self.width, self.polynom)
2014-11-03 12:54:41 -05:00
reg_i = Signal(self.width, reset=self.init)
self.sync += reg_i.eq(self.engine.next)
self.comb += [
self.engine.d.eq(self.d),
self.engine.last.eq(reg_i),
self.value.eq(reg_i),
self.error.eq(self.engine.next != self.check)
]
2014-11-04 11:35:46 -05:00
2015-01-16 17:52:41 -05:00
class LiteSATACRCInserter(CRCInserter):
2014-12-14 04:52:56 -05:00
def __init__(self, description):
2015-01-16 17:52:41 -05:00
CRCInserter.__init__(self, LiteSATACRC, description)
2014-11-04 11:35:46 -05:00
2015-01-16 17:52:41 -05:00
class LiteSATACRCChecker(CRCChecker):
2014-12-14 04:52:56 -05:00
def __init__(self, description):
2015-01-16 17:52:41 -05:00
CRCChecker.__init__(self, LiteSATACRC, description)