Source code for hwtLib.logic.crc
from hwt.bitmask import selectBit, mask
from hwt.code import If, Concat
from hwt.hdl.typeShortcuts import vec
from hwt.hdl.types.bits import Bits
from hwt.interfaces.std import VldSynced, VectSignal
from hwt.interfaces.utils import addClkRstn
from hwt.synthesizer.byteOrder import reversedBits
from hwt.synthesizer.unit import Unit
from hwt.synthesizer.param import Param
from hwt.synthesizer.vectorUtils import iterBits
from hwtLib.logic.crcPoly import CRC_5_USB, CRC_32
from hwtLib.logic.crcUtils import parsePolyStr, buildCrcMatrix
# http://stackoverflow.com/questions/41734560/parallel-crc-32-calculation-ethernet-10ge-mac
[docs]class Crc(Unit):
"""
Crc generator for any crc
polynom can be string in usual format or integer f.e."x^3+x+1" or 0b1011
"""
[docs] def _config(self):
self.DATA_WIDTH = Param(5)
self.POLY = Param(CRC_5_USB)
self.POLY_WIDTH = Param(5)
# also refin, reference in
self.REVERSE_IN = Param(False)
self.REVERSE_OUT = Param(False)
# also xorout
# output = this ^ value in reg
# for example ethernet has 0xffffffff
# (0 or mask(POLY_WIDTH) is automatically reduced)
self.FINAL_XOR_VAL = Param(0)
self.SEED = Param(0)
[docs] def _declr(self):
addClkRstn(self)
with self._paramsShared():
self.dataIn = VldSynced()
self.dataOut = VectSignal(self.POLY_WIDTH)
[docs] def wrapWithName(self, sig, name):
_sig = self._sig(name, sig._dtype)
_sig(sig)
return _sig
[docs] def parsePoly(self, POLY_WIDTH):
poly = int(self.POLY)
if isinstance(poly, str):
return parsePolyStr(poly, POLY_WIDTH)
elif isinstance(poly, int):
return [selectBit(poly, i) for i in range(POLY_WIDTH)]
else:
raise TypeError()
[docs] def build_CRC_XOR(self, inputBits, xorMatrix):
inputBits = list(inputBits)
crcBits = []
for regMask in xorMatrix:
bit = None
for m, b in zip(regMask, inputBits):
if m:
if bit is None:
bit = b
else:
bit = bit ^ b
crcBits.append(bit)
return crcBits
[docs] def _impl(self):
PW = int(self.POLY_WIDTH)
DW = int(self.DATA_WIDTH)
polyCoefs = self.parsePoly(PW)
regXorMatrix, dataXorMatrix = buildCrcMatrix(polyCoefs, PW, DW)
reg = self._reg("r",
Bits(self.POLY_WIDTH),
self.SEED)
# just rename to make code shorter
d = self.wrapWithName(self.dataIn.data, "d")
dataXorMatrix = iter(dataXorMatrix)
regCrcBits = self.build_CRC_XOR(iterBits(reg), regXorMatrix)
_dataBits = iterBits(d)
if self.REVERSE_IN:
_dataBits = reversed(list(_dataBits))
dataCrcBits = self.build_CRC_XOR(_dataBits, dataXorMatrix)
regNext = []
assert len(regCrcBits) == len(dataCrcBits)
for i, (dbit, rbit) in enumerate(zip(regCrcBits, dataCrcBits)):
if dbit is not None:
# just rename to make code shorter
dbit = self.wrapWithName(dbit, "d_%d" % i)
if rbit is not None:
# just rename to make code shorter
rbit = self.wrapWithName(rbit, "r_%d" % i)
if dbit is None:
bit = rbit
elif rbit is None:
bit = dbit
else:
bit = dbit ^ rbit
regNext.append(bit)
If(self.dataIn.vld,
# regNext is in format 0 ... N, we need to reverse it to litle endian
reg(Concat(*reversed(regNext)))
)
outXor = int(self.FINAL_XOR_VAL)
if self.REVERSE_OUT:
_reg = reversedBits(reg)
else:
_reg = reg
if outXor == 0:
self.dataOut(_reg)
elif outXor == mask(int(self.POLY_WIDTH)):
self.dataOut(~_reg)
else:
self.dataOut(_reg ^ self.FINAL_XOR_VAL)
if __name__ == "__main__":
from hwt.synthesizer.utils import toRtl
u = Crc()
u.POLY.set(CRC_32)
u.DATA_WIDTH.set(8)
u.POLY_WIDTH.set(32)
u.REVERSE_IN.set(True)
u.REVERSE_OUT.set(True)
u.FINAL_XOR_VAL.set(vec(mask(32), 32))
u.SEED.set(vec(mask(32), 32))
print(toRtl(u))