parent
60c2a1b4b8
commit
45b9730786
426
amaranth/lib/crc/__init__.py
Normal file
426
amaranth/lib/crc/__init__.py
Normal file
|
@ -0,0 +1,426 @@
|
|||
"""
|
||||
Utilities for computing cyclic redundancy checks (CRCs) in software and in
|
||||
hardware.
|
||||
|
||||
CRCs are specified using the :py:class:`Algorithm` class, which contains
|
||||
settings for CRC width, polynomial, initial value, input/output reflection, and
|
||||
output XOR. Many commonly used CRC algorithms are available in the
|
||||
:py:mod:`~amaranth.lib.crc.catalog` module, while most other CRC designs can be
|
||||
accommodated by manually constructing :py:class:`Algorithm`.
|
||||
|
||||
Call the :py:class:`Algorithm` with a ``data_width`` to obtain a
|
||||
:py:class:`Parameters` class, which fully defines a CRC computation. The
|
||||
:py:class:`Parameters` class provides the :py:meth:`~Parameters.compute` method
|
||||
to perform software computations, and the :py:meth:`~Parameters.create` method
|
||||
to create a hardware CRC module, :py:class:`Processor`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Create a predefined CRC16-CCITT hardware module, using the default
|
||||
# 8-bit data width (in other words, bytes).
|
||||
from amaranth.lib.crc.catalog import CRC16_CCITT
|
||||
crc = m.submodules.crc = CRC16_CCITT().create()
|
||||
|
||||
# Create a custom CRC algorithm, specify the data width explicitly,
|
||||
# and use it to compute a CRC value in software.
|
||||
from amaranth.lib.crc import Algorithm
|
||||
algo = Algorithm(crc_width=16, polynomial=0x1021, initial_crc=0xffff,
|
||||
reflect_input=False, reflect_output=False,
|
||||
xor_output=0x0000)
|
||||
assert algo(data_width=8).compute(b"123456789") == 0x29b1
|
||||
"""
|
||||
|
||||
from ... import *
|
||||
|
||||
__all__ = ["Algorithm", "Parameters", "Processor", "catalog"]
|
||||
|
||||
|
||||
class Algorithm:
|
||||
"""
|
||||
Settings for a CRC algorithm, excluding data width.
|
||||
|
||||
The parameter set is based on the Williams model from
|
||||
"A Painless Guide to CRC Error Detection Algorithms":
|
||||
http://www.ross.net/crc/download/crc_v3.txt
|
||||
|
||||
For a reference of standard CRC parameter sets, refer to:
|
||||
|
||||
* `reveng`_'s catalogue, which uses an identical parameterisation,
|
||||
* `crcmod`_'s list of predefined functions, but remove the leading '1'
|
||||
from the polynominal, XOR the "Init-value" with "XOR-out" to obtain
|
||||
``initial_crc``, and where "Reversed" is True, set both ``reflect_input``
|
||||
and ``reflect_output`` to True,
|
||||
* `CRC Zoo`_, which contains only polynomials; use the "explicit +1"
|
||||
form of polynomial but remove the leading '1'.
|
||||
|
||||
.. _reveng: https://reveng.sourceforge.io/crc-catalogue/all.htm
|
||||
.. _crcmod: http://crcmod.sourceforge.net/crcmod.predefined.html
|
||||
.. _CRC Zoo: https://users.ece.cmu.edu/~koopman/crc/
|
||||
|
||||
Many commonly used CRC algorithms are available in the
|
||||
:py:mod:`~amaranth.lib.crc.catalog` module, which includes
|
||||
all entries in the `reveng`_ catalogue.
|
||||
|
||||
To create a :py:class:`Parameters` instance, call the :py:class:`Algorithm`
|
||||
object with the required data width, which defaults to 8 bits.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
crc_width : int
|
||||
Bit width of CRC word. Also known as "width" in the Williams model.
|
||||
polynomial : int
|
||||
CRC polynomial to use, ``crc_width`` bits long, without the implicit
|
||||
``x**crc_width`` term. Polynomial is always specified with the highest
|
||||
order terms in the most significant bit positions; use
|
||||
``reflect_input`` and ``reflect_output`` to perform a least
|
||||
significant bit first computation.
|
||||
initial_crc : int
|
||||
Initial value of CRC register at reset. Most significant bit always
|
||||
corresponds to the highest order term in the CRC register.
|
||||
reflect_input : bool
|
||||
If True, the input data words are bit-reflected, so that they are
|
||||
processed least significant bit first.
|
||||
reflect_output : bool
|
||||
If True, the output CRC is bit-reflected, so the least-significant bit
|
||||
of the output is the highest-order bit of the CRC register.
|
||||
Note that this reflection is performed over the entire CRC register;
|
||||
for transmission you may want to treat the output as a little-endian
|
||||
multi-word value, so for example the reflected 16-bit output 0x4E4C
|
||||
would be transmitted as the two octets 0x4C 0x4E, each transmitted
|
||||
least significant bit first.
|
||||
xor_output : int
|
||||
The output CRC will be the CRC register XOR'd with this value, applied
|
||||
after any output bit-reflection.
|
||||
"""
|
||||
def __init__(self, *, crc_width, polynomial, initial_crc, reflect_input,
|
||||
reflect_output, xor_output):
|
||||
self.crc_width = int(crc_width)
|
||||
self.polynomial = int(polynomial)
|
||||
self.initial_crc = int(initial_crc)
|
||||
self.reflect_input = bool(reflect_input)
|
||||
self.reflect_output = bool(reflect_output)
|
||||
self.xor_output = int(xor_output)
|
||||
|
||||
if self.crc_width <= 0:
|
||||
raise ValueError("crc_width must be greater than 0")
|
||||
if not 0 <= self.polynomial < 2 ** self.crc_width:
|
||||
raise ValueError("polynomial must be between 0 and 2**crc_width - 1")
|
||||
if not 0 <= self.initial_crc < 2 ** self.crc_width:
|
||||
raise ValueError("initial_crc must be between 0 and 2**crc_width - 1")
|
||||
if not 0 <= self.xor_output < 2 ** self.crc_width:
|
||||
raise ValueError("xor_output must be between 0 and 2**crc_width - 1")
|
||||
|
||||
def __call__(self, data_width=8):
|
||||
"""
|
||||
Constructs a :py:class:`Parameters` instance from this
|
||||
:py:class:`Algorithm` with the specified ``data_width``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data_width : int
|
||||
Bit width of data words, default 8.
|
||||
"""
|
||||
return Parameters(self, data_width)
|
||||
|
||||
def __repr__(self):
|
||||
return f"Algorithm(crc_width={self.crc_width}," \
|
||||
f" polynomial=0x{self.polynomial:0{self.crc_width//4}x}," \
|
||||
f" initial_crc=0x{self.initial_crc:0{self.crc_width//4}x}," \
|
||||
f" reflect_input={self.reflect_input}," \
|
||||
f" reflect_output={self.reflect_output}," \
|
||||
f" xor_output=0x{self.xor_output:0{self.crc_width//4}x})"
|
||||
|
||||
|
||||
class Parameters:
|
||||
"""
|
||||
Full set of parameters for a CRC computation.
|
||||
|
||||
Contains the settings from :py:class:`Algorithm` and additionally
|
||||
``data_width``. Refer to :py:class:`Algorithm` for details of what each
|
||||
parameter means and how to construct them.
|
||||
|
||||
From this class, you can directly compute CRCs with the
|
||||
:py:meth:`~Parameters.compute` method, or construct a hardware module with
|
||||
the :py:meth:`~Parameters.create` method.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
algorithm : Algorithm
|
||||
CRC algorithm to use. Specifies the CRC width, polynomial,
|
||||
initial value, whether to reflect the input or output words,
|
||||
and any output XOR.
|
||||
data_width : int
|
||||
Bit width of data words.
|
||||
"""
|
||||
def __init__(self, algorithm, data_width=8):
|
||||
self._crc_width = algorithm.crc_width
|
||||
self._polynomial = algorithm.polynomial
|
||||
self._initial_crc = algorithm.initial_crc
|
||||
self._reflect_input = algorithm.reflect_input
|
||||
self._reflect_output = algorithm.reflect_output
|
||||
self._xor_output = algorithm.xor_output
|
||||
self._data_width = int(data_width)
|
||||
if self._data_width <= 0:
|
||||
raise ValueError("data_width must be greater than 0")
|
||||
|
||||
@property
|
||||
def algorithm(self):
|
||||
"""
|
||||
Returns an :py:class:`Algorithm` with the CRC settings from this
|
||||
instance.
|
||||
"""
|
||||
return Algorithm(
|
||||
crc_width=self._crc_width,
|
||||
polynomial=self._polynomial,
|
||||
initial_crc=self._initial_crc,
|
||||
reflect_input=self._reflect_input,
|
||||
reflect_output=self._reflect_output,
|
||||
xor_output=self._xor_output)
|
||||
|
||||
def residue(self):
|
||||
"""
|
||||
Compute the residue value for this CRC, which is the value left in the
|
||||
CRC register after processing any valid codeword.
|
||||
"""
|
||||
# Residue is computed by initialising to (possibly reflected)
|
||||
# xor_output, feeding crc_width worth of 0 bits, then taking
|
||||
# the (possibly reflected) output without any XOR.
|
||||
if self._reflect_output:
|
||||
init = self._reflect(self._xor_output, self._crc_width)
|
||||
else:
|
||||
init = self._xor_output
|
||||
algo = self.algorithm
|
||||
algo.initial_crc = init
|
||||
algo.reflect_input = False
|
||||
algo.xor_output = 0
|
||||
return algo(data_width=self._crc_width).compute([0])
|
||||
|
||||
def create(self):
|
||||
"""
|
||||
Returns a ``Processor`` configured with these parameters.
|
||||
"""
|
||||
return Processor(self)
|
||||
|
||||
def compute(self, data):
|
||||
"""
|
||||
Computes and returns the CRC of all data words in ``data``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data : iterable of integers
|
||||
The CRC is computed over this complete set of data.
|
||||
Each item is an integer of bitwidth equal to ``data_width``.
|
||||
"""
|
||||
# Precompute some constants we use every iteration.
|
||||
word_max = (1 << self._data_width) - 1
|
||||
top_bit = 1 << (self._crc_width + self._data_width - 1)
|
||||
crc_mask = (1 << (self._crc_width + self._data_width)) - 1
|
||||
poly_shifted = self._polynomial << self._data_width
|
||||
|
||||
# Implementation notes:
|
||||
# We always compute most-significant bit first, which means the
|
||||
# polynomial and initial value may be used as-is, and the reflect_in
|
||||
# and reflect_out values have their usual sense.
|
||||
# However, when computing word-at-a-time and MSbit-first, we must align
|
||||
# the input word so its MSbit lines up with the MSbit of the previous
|
||||
# CRC value. When the CRC width is smaller than the word width, this
|
||||
# would normally truncate data bits.
|
||||
# Instead, we shift the initial CRC left by the data width, and the
|
||||
# data word left by the crc width, lining up their MSbits no matter
|
||||
# the relation between the two widths.
|
||||
# The new CRC is then shifted right by the data width before output.
|
||||
|
||||
crc = self._initial_crc << self._data_width
|
||||
for word in data:
|
||||
if not 0 <= word <= word_max:
|
||||
raise ValueError("data word must be between 0 and {}".format(word_max - 1))
|
||||
|
||||
if self._reflect_input:
|
||||
word = self._reflect(word, self._data_width)
|
||||
|
||||
crc ^= word << self._crc_width
|
||||
for _ in range(self._data_width):
|
||||
if crc & top_bit:
|
||||
crc = (crc << 1) ^ poly_shifted
|
||||
else:
|
||||
crc <<= 1
|
||||
crc &= crc_mask
|
||||
|
||||
crc >>= self._data_width
|
||||
if self._reflect_output:
|
||||
crc = self._reflect(crc, self._crc_width)
|
||||
|
||||
crc ^= self._xor_output
|
||||
return crc
|
||||
|
||||
@staticmethod
|
||||
def _reflect(word, n):
|
||||
"""
|
||||
Bitwise-reflects an n-bit word ``word``.
|
||||
"""
|
||||
return int(f"{word:0{n}b}"[::-1], 2)
|
||||
|
||||
def _matrices(self):
|
||||
"""
|
||||
Computes the F and G matrices for parallel CRC computation, treating
|
||||
the CRC as a linear time-invariant system described by the state
|
||||
relation x(t+1) = F.x(i) + G.u(i), where x(i) and u(i) are column
|
||||
vectors of the bits of the CRC register and input word, F is the n-by-n
|
||||
matrix relating the old state to the new state, and G is the n-by-m
|
||||
matrix relating the new data to the new state, where n is the CRC
|
||||
width and m is the data word width.
|
||||
|
||||
The matrices are ordered least-significant-bit first; in other words
|
||||
the first entry, with index (0, 0), corresponds to the effect of the
|
||||
least-significant bit of the input on the least-significant bit of the
|
||||
output.
|
||||
|
||||
For convenience of implementation, both matrices are returned
|
||||
transposed: the first index is the input bit, and the second index is
|
||||
the corresponding output bit.
|
||||
|
||||
The matrices are used to select which bits are XORd together to compute
|
||||
each bit i of the new state: if F[j][i] is set then bit j of the old
|
||||
state is included in the XOR, and if G[j][i] is set then bit j of the
|
||||
new data is included.
|
||||
|
||||
These matrices are not affected by ``initial_crc``, ``reflect_input``,
|
||||
``reflect_output``, or ``xor_output``.
|
||||
"""
|
||||
f = []
|
||||
g = []
|
||||
algo = self.algorithm
|
||||
algo.reflect_input = algo.reflect_output = False
|
||||
algo.xor_output = 0
|
||||
crc = Parameters(algo, self._data_width)
|
||||
for i in range(self._crc_width):
|
||||
crc._initial_crc = 2 ** i
|
||||
w = crc.compute([0])
|
||||
f.append([int(x) for x in reversed(f"{w:0{self._crc_width}b}")])
|
||||
for i in range(self._data_width):
|
||||
crc._initial_crc = 0
|
||||
w = crc.compute([2 ** i])
|
||||
g.append([int(x) for x in reversed(f"{w:0{self._crc_width}b}")])
|
||||
return f, g
|
||||
|
||||
def __repr__(self):
|
||||
return f"Parameters({self.algorithm!r}, data_width={self._data_width})"
|
||||
|
||||
|
||||
class Processor(Elaboratable):
|
||||
"""
|
||||
Cyclic redundancy check (CRC) processor module.
|
||||
|
||||
This module generates CRCs from an input data stream, which can be used
|
||||
to validate an existing CRC or generate a new CRC. It is configured by
|
||||
the :py:class:`Parameters` class, which can handle most forms of CRCs.
|
||||
Refer to that class's documentation for a description of the parameters.
|
||||
|
||||
The CRC value is updated on any clock cycle where ``valid`` is asserted,
|
||||
with the updated value available on the ``crc`` output on the subsequent
|
||||
clock cycle. The latency is therefore one clock cycle, and the throughput
|
||||
is one data word per clock cycle.
|
||||
|
||||
The CRC is reset to its initial value whenever ``start`` is asserted.
|
||||
``start`` and ``valid`` may be asserted on the same clock cycle, in which
|
||||
case a new CRC computation is started with the current value of ``data``.
|
||||
|
||||
With ``data_width=1``, a classic bit-serial CRC is implemented for the
|
||||
given polynomial in a Galois-type shift register. For larger values of
|
||||
``data_width``, a similar architecture computes every new bit of the
|
||||
CRC in parallel.
|
||||
|
||||
The ``match_detected`` output may be used to validate data with a trailing
|
||||
CRC (also known as a codeword). If the most recently processed word(s) form
|
||||
the valid CRC of all the previous data since ``start`` was asserted, the
|
||||
CRC register will always take on a fixed value known as the residue. The
|
||||
``match_detected`` output indicates whether the CRC register currently
|
||||
contains this residue.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
parameters : Parameters
|
||||
CRC parameters.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
start : Signal(), in
|
||||
Assert to indicate the start of a CRC computation, re-initialising
|
||||
the CRC register to the initial value. May be asserted simultaneously
|
||||
with ``valid`` or by itself.
|
||||
data : Signal(data_width), in
|
||||
Data word to add to CRC when ``valid`` is asserted.
|
||||
valid : Signal(), in
|
||||
Assert when ``data`` is valid to add the data word to the CRC.
|
||||
crc : Signal(crc_width), out
|
||||
Registered CRC output value, updated one clock cycle after ``valid``
|
||||
becomes asserted.
|
||||
match_detected : Signal(), out
|
||||
Asserted if the current CRC value indicates a valid codeword has been
|
||||
received.
|
||||
"""
|
||||
def __init__(self, parameters):
|
||||
if not isinstance(parameters, Parameters):
|
||||
raise TypeError("Algorithmn parameters must be of type Parameters, "
|
||||
"not {!r}"
|
||||
.format(parameters))
|
||||
self._crc_width = parameters._crc_width
|
||||
self._data_width = parameters._data_width
|
||||
self._polynomial = parameters._polynomial
|
||||
self._initial_crc = Const(parameters._initial_crc, self._crc_width)
|
||||
self._reflect_input = parameters._reflect_input
|
||||
self._reflect_output = parameters._reflect_output
|
||||
self._xor_output = parameters._xor_output
|
||||
self._matrix_f, self._matrix_g = parameters._matrices()
|
||||
self._residue = parameters.residue()
|
||||
|
||||
self.start = Signal()
|
||||
self.data = Signal(self._data_width)
|
||||
self.valid = Signal()
|
||||
self.crc = Signal(self._crc_width)
|
||||
self.match_detected = Signal()
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
||||
crc_reg = Signal(self._crc_width, reset=self._initial_crc.value)
|
||||
data_in = Signal(self._data_width)
|
||||
|
||||
# Optionally bit-reflect input words.
|
||||
if self._reflect_input:
|
||||
m.d.comb += data_in.eq(self.data[::-1])
|
||||
else:
|
||||
m.d.comb += data_in.eq(self.data)
|
||||
|
||||
# Optionally bit-reflect and then XOR the output.
|
||||
if self._reflect_output:
|
||||
m.d.comb += self.crc.eq(crc_reg[::-1] ^ self._xor_output)
|
||||
else:
|
||||
m.d.comb += self.crc.eq(crc_reg ^ self._xor_output)
|
||||
|
||||
# Compute next CRC state.
|
||||
source = Mux(self.start, self._initial_crc, crc_reg)
|
||||
with m.If(self.valid):
|
||||
for i in range(self._crc_width):
|
||||
bit = 0
|
||||
for j in range(self._crc_width):
|
||||
if self._matrix_f[j][i]:
|
||||
bit ^= source[j]
|
||||
for j in range(self._data_width):
|
||||
if self._matrix_g[j][i]:
|
||||
bit ^= data_in[j]
|
||||
m.d.sync += crc_reg[i].eq(bit)
|
||||
with m.Elif(self.start):
|
||||
m.d.sync += crc_reg.eq(self._initial_crc)
|
||||
|
||||
# Check for residue match, indicating a valid codeword.
|
||||
if self._reflect_output:
|
||||
m.d.comb += self.match_detected.eq(crc_reg[::-1] == self._residue)
|
||||
else:
|
||||
m.d.comb += self.match_detected.eq(crc_reg == self._residue)
|
||||
|
||||
return m
|
||||
|
||||
|
||||
# Imported after Algorithm is defined to prevent circular imports.
|
||||
from . import catalog
|
918
amaranth/lib/crc/catalog.py
Normal file
918
amaranth/lib/crc/catalog.py
Normal file
|
@ -0,0 +1,918 @@
|
|||
"""
|
||||
This module contains a catalog of predefined CRC algorithms.
|
||||
|
||||
All entries are from `reveng`_, accessed on 2023-05-25.
|
||||
|
||||
.. _reveng: https://reveng.sourceforge.io/crc-catalogue/all.htm
|
||||
|
||||
To use an entry, call it with an optional ``data_width`` which defaults
|
||||
to 8. For example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
crc8 = m.submodules.crc8 = crc.catalog.CRC8_AUTOSAR().create()
|
||||
|
||||
"""
|
||||
|
||||
from . import Algorithm
|
||||
|
||||
# Note: The trailing `#:` gives Sphinx an empty documentation string for each
|
||||
# constant, allowing it to be documented with `automodule` (which otherwise
|
||||
# ignores undocumented module constants) and also preventing it from using
|
||||
# the Algorithm docstring if otherwise forced to document the constants.
|
||||
|
||||
CRC3_GSM = Algorithm(
|
||||
crc_width=3,
|
||||
polynomial=0x3,
|
||||
initial_crc=0x0,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x7) #:
|
||||
|
||||
CRC3_ROHC = Algorithm(
|
||||
crc_width=3,
|
||||
polynomial=0x3,
|
||||
initial_crc=0x7,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0) #:
|
||||
|
||||
CRC4_G_704 = CRC4_ITU = Algorithm(
|
||||
crc_width=4,
|
||||
polynomial=0x3,
|
||||
initial_crc=0x0,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0) #:
|
||||
|
||||
CRC4_INTERLAKEN = Algorithm(
|
||||
crc_width=4,
|
||||
polynomial=0x3,
|
||||
initial_crc=0xf,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xf) #:
|
||||
|
||||
CRC5_EPC_C1G2 = CRC5_EPC = Algorithm(
|
||||
crc_width=5,
|
||||
polynomial=0x09,
|
||||
initial_crc=0x09,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC5_G_704 = CRC5_ITU = Algorithm(
|
||||
crc_width=5,
|
||||
polynomial=0x15,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC5_USB = Algorithm(
|
||||
crc_width=5,
|
||||
polynomial=0x05,
|
||||
initial_crc=0x1f,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x1f) #:
|
||||
|
||||
CRC6_CDMA2000_A = Algorithm(
|
||||
crc_width=6,
|
||||
polynomial=0x27,
|
||||
initial_crc=0x3f,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC6_CDMA2000_B = Algorithm(
|
||||
crc_width=6,
|
||||
polynomial=0x07,
|
||||
initial_crc=0x3f,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC6_DARC = Algorithm(
|
||||
crc_width=6,
|
||||
polynomial=0x19,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC6_G_704 = CRC6_ITU = Algorithm(
|
||||
crc_width=6,
|
||||
polynomial=0x03,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC6_GSM = Algorithm(
|
||||
crc_width=6,
|
||||
polynomial=0x2f,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x3f) #:
|
||||
|
||||
CRC7_MMC = Algorithm(
|
||||
crc_width=7,
|
||||
polynomial=0x09,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC7_ROHC = Algorithm(
|
||||
crc_width=7,
|
||||
polynomial=0x4f,
|
||||
initial_crc=0x7f,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC7_UMTS = Algorithm(
|
||||
crc_width=7,
|
||||
polynomial=0x45,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_AUTOSAR = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x2f,
|
||||
initial_crc=0xff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xff) #:
|
||||
|
||||
CRC8_BLUETOOTH = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0xa7,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_CDMA2000 = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x9b,
|
||||
initial_crc=0xff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_DARC = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x39,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_DVB_S2 = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0xd5,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_GSM_A = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x1d,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_GSM_B = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x49,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xff) #:
|
||||
|
||||
CRC8_HITAG = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x1d,
|
||||
initial_crc=0xff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_I_432_1 = CRC8_ITU = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x07,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x55) #:
|
||||
|
||||
CRC8_I_CODE = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x1d,
|
||||
initial_crc=0xfd,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_LTE = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x9b,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_MAXIM_DOW = CRC8_MAXIM = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x31,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_MIFARE_MAD = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x1d,
|
||||
initial_crc=0xc7,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_NRSC_5 = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x31,
|
||||
initial_crc=0xff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_OPENSAFETY = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x2f,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_ROHC = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x07,
|
||||
initial_crc=0xff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_SAE_J1850 = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x1d,
|
||||
initial_crc=0xff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xff) #:
|
||||
|
||||
CRC8_SMBUS = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x07,
|
||||
initial_crc=0x00,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_TECH_3250 = CRC8_AES = CRC8_ETU = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x1d,
|
||||
initial_crc=0xff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC8_WCDMA = Algorithm(
|
||||
crc_width=8,
|
||||
polynomial=0x9b,
|
||||
initial_crc=0x00,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00) #:
|
||||
|
||||
CRC10_ATM = CRC10_I_610 = Algorithm(
|
||||
crc_width=10,
|
||||
polynomial=0x233,
|
||||
initial_crc=0x000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC10_CDMA2000 = Algorithm(
|
||||
crc_width=10,
|
||||
polynomial=0x3d9,
|
||||
initial_crc=0x3ff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC10_GSM = Algorithm(
|
||||
crc_width=10,
|
||||
polynomial=0x175,
|
||||
initial_crc=0x000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x3ff) #:
|
||||
|
||||
CRC11_FLEXRAY = Algorithm(
|
||||
crc_width=11,
|
||||
polynomial=0x385,
|
||||
initial_crc=0x01a,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC11_UMTS = Algorithm(
|
||||
crc_width=11,
|
||||
polynomial=0x307,
|
||||
initial_crc=0x000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC12_CDMA2000 = Algorithm(
|
||||
crc_width=12,
|
||||
polynomial=0xf13,
|
||||
initial_crc=0xfff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC12_DECT = Algorithm(
|
||||
crc_width=12,
|
||||
polynomial=0x80f,
|
||||
initial_crc=0x000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC12_GSM = Algorithm(
|
||||
crc_width=12,
|
||||
polynomial=0xd31,
|
||||
initial_crc=0x000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xfff) #:
|
||||
|
||||
CRC12_UMTS = CRC12_3GPP = Algorithm(
|
||||
crc_width=12,
|
||||
polynomial=0x80f,
|
||||
initial_crc=0x000,
|
||||
reflect_input=False,
|
||||
reflect_output=True,
|
||||
xor_output=0x000) #:
|
||||
|
||||
CRC13_BBC = Algorithm(
|
||||
crc_width=13,
|
||||
polynomial=0x1cf5,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC14_DARC = Algorithm(
|
||||
crc_width=14,
|
||||
polynomial=0x0805,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC14_GSM = Algorithm(
|
||||
crc_width=14,
|
||||
polynomial=0x202d,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x3fff) #:
|
||||
|
||||
CRC15_CAN = Algorithm(
|
||||
crc_width=15,
|
||||
polynomial=0x4599,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC15_MPT1327 = Algorithm(
|
||||
crc_width=15,
|
||||
polynomial=0x6815,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0001) #:
|
||||
|
||||
CRC16_ARC = CRC16_IBM = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_CDMA2000 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0xc867,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_CMS = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_DDS_110 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0x800d,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_DECT_R = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x0589,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0001) #:
|
||||
|
||||
CRC16_DECT_X = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x0589,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_DNP = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x3d65,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_EN_13757 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x3d65,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_GENIBUS = CRC16_DARC = CRC16_EPC = CRC16_EPC_C1G2 = CRC16_I_CODE = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_GSM = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_IBM_3740 = CRC16_AUTOSAR = CRC16_CCITT_FALSE = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_IBM_SDLC = CRC16_ISO_HDLC = CRC16_ISO_IEC_14443_3_B = CRC16_X25 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_ISO_IEC_14443_3_A = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0xc6c6,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_KERMIT = CRC16_BLUETOOTH = CRC16_CCITT = CRC16_CCITT_TRUE = CRC16_V_41_LSB = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_LJ1200 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x6f63,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_M17 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x5935,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_MAXIM_DOW = CRC16_MAXIM = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_MCRF4XX = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_MODBUS = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_NRSC_5 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x080b,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_OPENSAFETY_A = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x5935,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_OPENSAFETY_B = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x755b,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_PROFIBUS = CRC16_IEC_61158_2 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1dcf,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_RIELLO = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0xb2aa,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_SPI_FUJITSU = CRC16_AUG_CCITT = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0x1d0f,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_T10_DIF = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8bb7,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_TELEDISK = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0xa097,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_TMS37157 = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0x89ec,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_UMTS = CRC16_BUYPASS = CRC16_VERIFONE = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC16_USB = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x8005,
|
||||
initial_crc=0xffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffff) #:
|
||||
|
||||
CRC16_XMODEM = CRC16_ACORN = CRC16_LTE = CRC16_V_41_MSB = CRC16_ZMODEM = Algorithm(
|
||||
crc_width=16,
|
||||
polynomial=0x1021,
|
||||
initial_crc=0x0000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000) #:
|
||||
|
||||
CRC17_CAN_FD = Algorithm(
|
||||
crc_width=17,
|
||||
polynomial=0x1685b,
|
||||
initial_crc=0x00000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00000) #:
|
||||
|
||||
CRC21_CAN_FD = Algorithm(
|
||||
crc_width=21,
|
||||
polynomial=0x102899,
|
||||
initial_crc=0x000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_BLE = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x00065b,
|
||||
initial_crc=0x555555,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_FLEXRAY_A = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x5d6dcb,
|
||||
initial_crc=0xfedcba,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_FLEXRAY_B = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x5d6dcb,
|
||||
initial_crc=0xabcdef,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_INTERLAKEN = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x328b63,
|
||||
initial_crc=0xffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffffff) #:
|
||||
|
||||
CRC24_LTE_A = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x864cfb,
|
||||
initial_crc=0x000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_LTE_B = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x800063,
|
||||
initial_crc=0x000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_OPENPGP = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x864cfb,
|
||||
initial_crc=0xb704ce,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x000000) #:
|
||||
|
||||
CRC24_OS_9 = Algorithm(
|
||||
crc_width=24,
|
||||
polynomial=0x800063,
|
||||
initial_crc=0xffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffffff) #:
|
||||
|
||||
CRC30_CDMA = Algorithm(
|
||||
crc_width=30,
|
||||
polynomial=0x2030b9c7,
|
||||
initial_crc=0x3fffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x3fffffff) #:
|
||||
|
||||
CRC31_PHILIPS = Algorithm(
|
||||
crc_width=31,
|
||||
polynomial=0x04c11db7,
|
||||
initial_crc=0x7fffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x7fffffff) #:
|
||||
|
||||
CRC32_AIXM = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x814141ab,
|
||||
initial_crc=0x00000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00000000) #:
|
||||
|
||||
CRC32_AUTOSAR = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0xf4acfb13,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffffffff) #:
|
||||
|
||||
CRC32_BASE91_D = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0xa833982b,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffffffff) #:
|
||||
|
||||
CRC32_BZIP2 = CRC32_AAL5 = CRC32_DECT_B = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x04c11db7,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffffffff) #:
|
||||
|
||||
CRC32_CD_ROM_EDC = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x8001801b,
|
||||
initial_crc=0x00000000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00000000) #:
|
||||
|
||||
CRC32_CKSUM = CRC32_POSIX = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x04c11db7,
|
||||
initial_crc=0x00000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffffffff) #:
|
||||
|
||||
CRC32_ISCSI = CRC32_BASE91_C = CRC32_CASTAGNOLI = CRC32_INTERLAKEN = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x1edc6f41,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffffffff) #:
|
||||
|
||||
CRC32_ISO_HDLC = CRC32_ADCCP = CRC32_V_42 = CRC32_XZ = CRC32_PKZIP = CRC32_ETHERNET = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x04c11db7,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffffffff) #:
|
||||
|
||||
CRC32_JAMCRC = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x04c11db7,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00000000) #:
|
||||
|
||||
CRC32_MEF = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x741b8cd7,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x00000000) #:
|
||||
|
||||
CRC32_MPEG_2 = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x04c11db7,
|
||||
initial_crc=0xffffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00000000) #:
|
||||
|
||||
CRC32_XFER = Algorithm(
|
||||
crc_width=32,
|
||||
polynomial=0x000000af,
|
||||
initial_crc=0x00000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x00000000) #:
|
||||
|
||||
CRC40_GSM = Algorithm(
|
||||
crc_width=40,
|
||||
polynomial=0x0004820009,
|
||||
initial_crc=0x0000000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffffffffff) #:
|
||||
|
||||
CRC64_ECMA_182 = Algorithm(
|
||||
crc_width=64,
|
||||
polynomial=0x42f0e1eba9ea3693,
|
||||
initial_crc=0x0000000000000000,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0x0000000000000000) #:
|
||||
|
||||
CRC64_GO_ISO = Algorithm(
|
||||
crc_width=64,
|
||||
polynomial=0x000000000000001b,
|
||||
initial_crc=0xffffffffffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffffffffffffffff) #:
|
||||
|
||||
CRC64_MS = Algorithm(
|
||||
crc_width=64,
|
||||
polynomial=0x259c84cba6426349,
|
||||
initial_crc=0xffffffffffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000000000000000) #:
|
||||
|
||||
CRC64_REDIS = Algorithm(
|
||||
crc_width=64,
|
||||
polynomial=0xad93d23594c935a9,
|
||||
initial_crc=0x0000000000000000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x0000000000000000) #:
|
||||
|
||||
CRC64_WE = Algorithm(
|
||||
crc_width=64,
|
||||
polynomial=0x42f0e1eba9ea3693,
|
||||
initial_crc=0xffffffffffffffff,
|
||||
reflect_input=False,
|
||||
reflect_output=False,
|
||||
xor_output=0xffffffffffffffff) #:
|
||||
|
||||
CRC64_XZ = CRC64_ECMA = Algorithm(
|
||||
crc_width=64,
|
||||
polynomial=0x42f0e1eba9ea3693,
|
||||
initial_crc=0xffffffffffffffff,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0xffffffffffffffff) #:
|
||||
|
||||
CRC82_DARC = Algorithm(
|
||||
crc_width=82,
|
||||
polynomial=0x0308c0111011401440411,
|
||||
initial_crc=0x000000000000000000000,
|
||||
reflect_input=True,
|
||||
reflect_output=True,
|
||||
xor_output=0x000000000000000000000) #:
|
|
@ -35,6 +35,9 @@ Implemented RFCs
|
|||
.. _RFC 3: https://amaranth-lang.org/rfcs/0003-enumeration-shapes.html
|
||||
.. _RFC 4: https://amaranth-lang.org/rfcs/0004-const-castable-exprs.html
|
||||
.. _RFC 5: https://amaranth-lang.org/rfcs/0005-remove-const-normalize.html
|
||||
.. _RFC 6: https://amaranth-lang.org/rfcs/0006-stdlib-crc.html
|
||||
.. _RFC 8: https://amaranth-lang.org/rfcs/0008-aggregate-extensibility.html
|
||||
.. _RFC 9: https://amaranth-lang.org/rfcs/0009-const-init-shape-castable.html
|
||||
.. _RFC 8: https://amaranth-lang.org/rfcs/0008-aggregate-extensibility.html
|
||||
.. _RFC 9: https://amaranth-lang.org/rfcs/0009-const-init-shape-castable.html
|
||||
.. _RFC 10: https://amaranth-lang.org/rfcs/0010-move-repl-to-value.html
|
||||
|
@ -44,6 +47,9 @@ Implemented RFCs
|
|||
* `RFC 3`_: Enumeration shapes
|
||||
* `RFC 4`_: Constant-castable expressions
|
||||
* `RFC 5`_: Remove Const.normalize
|
||||
* `RFC 6`_: CRC generator
|
||||
* `RFC 8`_: Aggregate extensibility
|
||||
* `RFC 9`_: Constant initialization for shape-castable objects
|
||||
* `RFC 8`_: Aggregate extensibility
|
||||
* `RFC 9`_: Constant initialization for shape-castable objects
|
||||
* `RFC 10`_: Move Repl to Value.replicate
|
||||
|
@ -79,6 +85,7 @@ Standard library changes
|
|||
|
||||
* Added: :mod:`amaranth.lib.enum`. (`RFC 3`_)
|
||||
* Added: :mod:`amaranth.lib.data`. (`RFC 1`_)
|
||||
* Added: :mod:`amaranth.lib.crc`. (`RFC 6`_)
|
||||
|
||||
|
||||
Toolchain changes
|
||||
|
|
|
@ -12,4 +12,5 @@ Standard library
|
|||
stdlib/data
|
||||
stdlib/coding
|
||||
stdlib/cdc
|
||||
stdlib/crc
|
||||
stdlib/fifo
|
||||
|
|
11
docs/stdlib/crc.rst
Normal file
11
docs/stdlib/crc.rst
Normal file
|
@ -0,0 +1,11 @@
|
|||
Cyclic redundancy checks
|
||||
########################
|
||||
|
||||
.. automodule:: amaranth.lib.crc
|
||||
:special-members: __call__
|
||||
|
||||
The following pre-defined CRC algorithms are available:
|
||||
|
||||
.. toctree::
|
||||
|
||||
crc/catalog
|
4
docs/stdlib/crc/catalog.rst
Normal file
4
docs/stdlib/crc/catalog.rst
Normal file
|
@ -0,0 +1,4 @@
|
|||
Predefined CRC Algorithms
|
||||
#########################
|
||||
|
||||
.. automodule:: amaranth.lib.crc.catalog
|
350
tests/test_lib_crc.py
Normal file
350
tests/test_lib_crc.py
Normal file
|
@ -0,0 +1,350 @@
|
|||
# amaranth: UnusedElaboratable=no
|
||||
|
||||
import unittest
|
||||
|
||||
from amaranth.sim import *
|
||||
from amaranth.lib.crc import Algorithm, Processor, catalog
|
||||
|
||||
|
||||
# Subset of catalogue CRCs used to test the hardware CRC implementation,
|
||||
# as testing all algorithms takes a long time for little benefit.
|
||||
# Selected to ensure coverage of CRC width, initial value, reflection, and
|
||||
# XOR output.
|
||||
CRCS = [
|
||||
"CRC3_GSM", "CRC4_INTERLAKEN", "CRC5_USB", "CRC8_AUTOSAR", "CRC8_BLUETOOTH",
|
||||
"CRC8_I_432_1", "CRC12_UMTS", "CRC15_CAN", "CRC16_ARC", "CRC16_IBM_3740",
|
||||
"CRC17_CAN_FD", "CRC21_CAN_FD", "CRC24_FLEXRAY_A", "CRC32_AUTOSAR",
|
||||
"CRC32_BZIP2", "CRC32_ISO_HDLC", "CRC40_GSM"
|
||||
]
|
||||
|
||||
# All catalogue CRCs with their associated check values and residues from
|
||||
# the reveng catalogue. Used to verify our computation of the check and
|
||||
# residue values.
|
||||
CRC_CHECKS = {
|
||||
"CRC3_GSM": (0x4, 0x2),
|
||||
"CRC3_ROHC": (0x6, 0x0),
|
||||
"CRC4_G_704": (0x7, 0x0),
|
||||
"CRC4_ITU": (0x7, 0x0),
|
||||
"CRC4_INTERLAKEN": (0xb, 0x2),
|
||||
"CRC5_EPC_C1G2": (0x00, 0x00),
|
||||
"CRC5_EPC": (0x00, 0x00),
|
||||
"CRC5_G_704": (0x07, 0x00),
|
||||
"CRC5_ITU": (0x07, 0x00),
|
||||
"CRC5_USB": (0x19, 0x06),
|
||||
"CRC6_CDMA2000_A": (0x0d, 0x00),
|
||||
"CRC6_CDMA2000_B": (0x3b, 0x00),
|
||||
"CRC6_DARC": (0x26, 0x00),
|
||||
"CRC6_G_704": (0x06, 0x00),
|
||||
"CRC6_ITU": (0x06, 0x00),
|
||||
"CRC6_GSM": (0x13, 0x3a),
|
||||
"CRC7_MMC": (0x75, 0x00),
|
||||
"CRC7_ROHC": (0x53, 0x00),
|
||||
"CRC7_UMTS": (0x61, 0x00),
|
||||
"CRC8_AUTOSAR": (0xdf, 0x42),
|
||||
"CRC8_BLUETOOTH": (0x26, 0x00),
|
||||
"CRC8_CDMA2000": (0xda, 0x00),
|
||||
"CRC8_DARC": (0x15, 0x00),
|
||||
"CRC8_DVB_S2": (0xbc, 0x00),
|
||||
"CRC8_GSM_A": (0x37, 0x00),
|
||||
"CRC8_GSM_B": (0x94, 0x53),
|
||||
"CRC8_HITAG": (0xb4, 0x00),
|
||||
"CRC8_I_432_1": (0xa1, 0xac),
|
||||
"CRC8_ITU": (0xa1, 0xac),
|
||||
"CRC8_I_CODE": (0x7e, 0x00),
|
||||
"CRC8_LTE": (0xea, 0x00),
|
||||
"CRC8_MAXIM_DOW": (0xa1, 0x00),
|
||||
"CRC8_MAXIM": (0xa1, 0x00),
|
||||
"CRC8_MIFARE_MAD": (0x99, 0x00),
|
||||
"CRC8_NRSC_5": (0xf7, 0x00),
|
||||
"CRC8_OPENSAFETY": (0x3e, 0x00),
|
||||
"CRC8_ROHC": (0xd0, 0x00),
|
||||
"CRC8_SAE_J1850": (0x4b, 0xc4),
|
||||
"CRC8_SMBUS": (0xf4, 0x00),
|
||||
"CRC8_TECH_3250": (0x97, 0x00),
|
||||
"CRC8_AES": (0x97, 0x00),
|
||||
"CRC8_ETU": (0x97, 0x00),
|
||||
"CRC8_WCDMA": (0x25, 0x00),
|
||||
"CRC10_ATM": (0x199, 0x000),
|
||||
"CRC10_I_610": (0x199, 0x000),
|
||||
"CRC10_CDMA2000": (0x233, 0x000),
|
||||
"CRC10_GSM": (0x12a, 0x0c6),
|
||||
"CRC11_FLEXRAY": (0x5a3, 0x000),
|
||||
"CRC11_UMTS": (0x061, 0x000),
|
||||
"CRC12_CDMA2000": (0xd4d, 0x000),
|
||||
"CRC12_DECT": (0xf5b, 0x000),
|
||||
"CRC12_GSM": (0xb34, 0x178),
|
||||
"CRC12_UMTS": (0xdaf, 0x000),
|
||||
"CRC12_3GPP": (0xdaf, 0x000),
|
||||
"CRC13_BBC": (0x04fa, 0x0000),
|
||||
"CRC14_DARC": (0x082d, 0x0000),
|
||||
"CRC14_GSM": (0x30ae, 0x031e),
|
||||
"CRC15_CAN": (0x059e, 0x0000),
|
||||
"CRC15_MPT1327": (0x2566, 0x6815),
|
||||
"CRC16_ARC": (0xbb3d, 0x0000),
|
||||
"CRC16_IBM": (0xbb3d, 0x0000),
|
||||
"CRC16_CDMA2000": (0x4c06, 0x0000),
|
||||
"CRC16_CMS": (0xaee7, 0x0000),
|
||||
"CRC16_DDS_110": (0x9ecf, 0x0000),
|
||||
"CRC16_DECT_R": (0x007e, 0x0589),
|
||||
"CRC16_DECT_X": (0x007f, 0x0000),
|
||||
"CRC16_DNP": (0xea82, 0x66c5),
|
||||
"CRC16_EN_13757": (0xc2b7, 0xa366),
|
||||
"CRC16_GENIBUS": (0xd64e, 0x1d0f),
|
||||
"CRC16_DARC": (0xd64e, 0x1d0f),
|
||||
"CRC16_EPC": (0xd64e, 0x1d0f),
|
||||
"CRC16_EPC_C1G2": (0xd64e, 0x1d0f),
|
||||
"CRC16_I_CODE": (0xd64e, 0x1d0f),
|
||||
"CRC16_GSM": (0xce3c, 0x1d0f),
|
||||
"CRC16_IBM_3740": (0x29b1, 0x0000),
|
||||
"CRC16_AUTOSAR": (0x29b1, 0x0000),
|
||||
"CRC16_CCITT_FALSE": (0x29b1, 0x0000),
|
||||
"CRC16_IBM_SDLC": (0x906e, 0xf0b8),
|
||||
"CRC16_ISO_HDLC": (0x906e, 0xf0b8),
|
||||
"CRC16_ISO_IEC_14443_3_B": (0x906e, 0xf0b8),
|
||||
"CRC16_X25": (0x906e, 0xf0b8),
|
||||
"CRC16_ISO_IEC_14443_3_A": (0xbf05, 0x0000),
|
||||
"CRC16_KERMIT": (0x2189, 0x0000),
|
||||
"CRC16_BLUETOOTH": (0x2189, 0x0000),
|
||||
"CRC16_CCITT": (0x2189, 0x0000),
|
||||
"CRC16_CCITT_TRUE": (0x2189, 0x0000),
|
||||
"CRC16_V_41_LSB": (0x2189, 0x0000),
|
||||
"CRC16_LJ1200": (0xbdf4, 0x0000),
|
||||
"CRC16_M17": (0x772b, 0x0000),
|
||||
"CRC16_MAXIM_DOW": (0x44c2, 0xb001),
|
||||
"CRC16_MAXIM": (0x44c2, 0xb001),
|
||||
"CRC16_MCRF4XX": (0x6f91, 0x0000),
|
||||
"CRC16_MODBUS": (0x4b37, 0x0000),
|
||||
"CRC16_NRSC_5": (0xa066, 0x0000),
|
||||
"CRC16_OPENSAFETY_A": (0x5d38, 0x0000),
|
||||
"CRC16_OPENSAFETY_B": (0x20fe, 0x0000),
|
||||
"CRC16_PROFIBUS": (0xa819, 0xe394),
|
||||
"CRC16_IEC_61158_2": (0xa819, 0xe394),
|
||||
"CRC16_RIELLO": (0x63d0, 0x0000),
|
||||
"CRC16_SPI_FUJITSU": (0xe5cc, 0x0000),
|
||||
"CRC16_AUG_CCITT": (0xe5cc, 0x0000),
|
||||
"CRC16_T10_DIF": (0xd0db, 0x0000),
|
||||
"CRC16_TELEDISK": (0x0fb3, 0x0000),
|
||||
"CRC16_TMS37157": (0x26b1, 0x0000),
|
||||
"CRC16_UMTS": (0xfee8, 0x0000),
|
||||
"CRC16_BUYPASS": (0xfee8, 0x0000),
|
||||
"CRC16_VERIFONE": (0xfee8, 0x0000),
|
||||
"CRC16_USB": (0xb4c8, 0xb001),
|
||||
"CRC16_XMODEM": (0x31c3, 0x0000),
|
||||
"CRC16_ACORN": (0x31c3, 0x0000),
|
||||
"CRC16_LTE": (0x31c3, 0x0000),
|
||||
"CRC16_V_41_MSB": (0x31c3, 0x0000),
|
||||
"CRC16_ZMODEM": (0x31c3, 0x0000),
|
||||
"CRC17_CAN_FD": (0x04f03, 0x00000),
|
||||
"CRC21_CAN_FD": (0x0ed841, 0x000000),
|
||||
"CRC24_BLE": (0xc25a56, 0x000000),
|
||||
"CRC24_FLEXRAY_A": (0x7979bd, 0x000000),
|
||||
"CRC24_FLEXRAY_B": (0x1f23b8, 0x000000),
|
||||
"CRC24_INTERLAKEN": (0xb4f3e6, 0x144e63),
|
||||
"CRC24_LTE_A": (0xcde703, 0x000000),
|
||||
"CRC24_LTE_B": (0x23ef52, 0x000000),
|
||||
"CRC24_OPENPGP": (0x21cf02, 0x000000),
|
||||
"CRC24_OS_9": (0x200fa5, 0x800fe3),
|
||||
"CRC30_CDMA": (0x04c34abf, 0x34efa55a),
|
||||
"CRC31_PHILIPS": (0x0ce9e46c, 0x4eaf26f1),
|
||||
"CRC32_AIXM": (0x3010bf7f, 0x00000000),
|
||||
"CRC32_AUTOSAR": (0x1697d06a, 0x904cddbf),
|
||||
"CRC32_BASE91_D": (0x87315576, 0x45270551),
|
||||
"CRC32_BZIP2": (0xfc891918, 0xc704dd7b),
|
||||
"CRC32_AAL5": (0xfc891918, 0xc704dd7b),
|
||||
"CRC32_DECT_B": (0xfc891918, 0xc704dd7b),
|
||||
"CRC32_CD_ROM_EDC": (0x6ec2edc4, 0x00000000),
|
||||
"CRC32_CKSUM": (0x765e7680, 0xc704dd7b),
|
||||
"CRC32_POSIX": (0x765e7680, 0xc704dd7b),
|
||||
"CRC32_ISCSI": (0xe3069283, 0xb798b438),
|
||||
"CRC32_BASE91_C": (0xe3069283, 0xb798b438),
|
||||
"CRC32_CASTAGNOLI": (0xe3069283, 0xb798b438),
|
||||
"CRC32_INTERLAKEN": (0xe3069283, 0xb798b438),
|
||||
"CRC32_ISO_HDLC": (0xcbf43926, 0xdebb20e3),
|
||||
"CRC32_ADCCP": (0xcbf43926, 0xdebb20e3),
|
||||
"CRC32_V_42": (0xcbf43926, 0xdebb20e3),
|
||||
"CRC32_XZ": (0xcbf43926, 0xdebb20e3),
|
||||
"CRC32_PKZIP": (0xcbf43926, 0xdebb20e3),
|
||||
"CRC32_ETHERNET": (0xcbf43926, 0xdebb20e3),
|
||||
"CRC32_JAMCRC": (0x340bc6d9, 0x00000000),
|
||||
"CRC32_MEF": (0xd2c22f51, 0x00000000),
|
||||
"CRC32_MPEG_2": (0x0376e6e7, 0x00000000),
|
||||
"CRC32_XFER": (0xbd0be338, 0x00000000),
|
||||
"CRC40_GSM": (0xd4164fc646, 0xc4ff8071ff),
|
||||
"CRC64_ECMA_182": (0x6c40df5f0b497347, 0x0000000000000000),
|
||||
"CRC64_GO_ISO": (0xb90956c775a41001, 0x5300000000000000),
|
||||
"CRC64_MS": (0x75d4b74f024eceea, 0x0000000000000000),
|
||||
"CRC64_REDIS": (0xe9c6d914c4b8d9ca, 0x0000000000000000),
|
||||
"CRC64_WE": (0x62ec59e3f1a4f00a, 0xfcacbebd5931a992),
|
||||
"CRC64_XZ": (0x995dc9bbdf1939fa, 0x49958c9abd7d353f),
|
||||
"CRC64_ECMA": (0x995dc9bbdf1939fa, 0x49958c9abd7d353f),
|
||||
"CRC82_DARC": (0x09ea83f625023801fd612, 0x000000000000000000000),
|
||||
}
|
||||
|
||||
|
||||
class CRCTestCase(unittest.TestCase):
|
||||
def test_checks(self):
|
||||
"""
|
||||
Verify computed check values and residues match catalogue entries.
|
||||
"""
|
||||
for name in dir(catalog):
|
||||
if name.startswith("CRC"):
|
||||
crc = getattr(catalog, name)(data_width=8)
|
||||
check, residue = CRC_CHECKS[name]
|
||||
assert crc.compute(b"123456789") == check
|
||||
assert crc.residue() == residue
|
||||
|
||||
def test_repr(self):
|
||||
algorithm = catalog.CRC8_AUTOSAR
|
||||
assert repr(algorithm) == "Algorithm(crc_width=8, polynomial=0x2f," \
|
||||
" initial_crc=0xff, reflect_input=False, reflect_output=False," \
|
||||
" xor_output=0xff)"
|
||||
|
||||
params = algorithm(data_width=8)
|
||||
assert repr(params) == "Parameters(Algorithm(crc_width=8," \
|
||||
" polynomial=0x2f, initial_crc=0xff, reflect_input=False," \
|
||||
" reflect_output=False, xor_output=0xff), data_width=8)"
|
||||
|
||||
def test_processor_typecheck(self):
|
||||
with self.assertRaises(TypeError):
|
||||
proc = Processor(12)
|
||||
|
||||
def test_algorithm_range_checks(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Algorithm(crc_width=0, polynomial=0x3, initial_crc=0x0,
|
||||
reflect_input=False, reflect_output=False, xor_output=0x7)
|
||||
with self.assertRaises(ValueError):
|
||||
Algorithm(crc_width=3, polynomial=0x8, initial_crc=0x0,
|
||||
reflect_input=False, reflect_output=False, xor_output=0x7)
|
||||
with self.assertRaises(ValueError):
|
||||
Algorithm(crc_width=3, polynomial=0x3, initial_crc=0x8,
|
||||
reflect_input=False, reflect_output=False, xor_output=0x7)
|
||||
with self.assertRaises(ValueError):
|
||||
Algorithm(crc_width=3, polynomial=0x3, initial_crc=0x0,
|
||||
reflect_input=False, reflect_output=False, xor_output=0x8)
|
||||
|
||||
def test_parameter_range_checks(self):
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.CRC8_AUTOSAR(data_width=0)
|
||||
with self.assertRaises(ValueError):
|
||||
crc = catalog.CRC8_AUTOSAR()
|
||||
crc.compute([3, 4, 256])
|
||||
|
||||
def test_crc_bytes(self):
|
||||
"""
|
||||
Verify CRC generation by computing the check value for each CRC
|
||||
in the catalogue with byte-sized inputs.
|
||||
"""
|
||||
for name in CRCS:
|
||||
crc = getattr(catalog, name)(data_width=8).create()
|
||||
check = CRC_CHECKS[name][0]
|
||||
|
||||
def process():
|
||||
for word in b"123456789":
|
||||
yield crc.start.eq(word == b"1")
|
||||
yield crc.data.eq(word)
|
||||
yield crc.valid.eq(1)
|
||||
yield
|
||||
yield crc.valid.eq(0)
|
||||
yield
|
||||
self.assertEqual((yield crc.crc), check)
|
||||
|
||||
sim = Simulator(crc)
|
||||
sim.add_sync_process(process)
|
||||
sim.add_clock(1e-6)
|
||||
sim.run()
|
||||
|
||||
def test_crc_words(self):
|
||||
"""
|
||||
Verify CRC generation for non-byte-sized data by computing a check
|
||||
value for 1, 2, 4, 16, 32, and 64-bit inputs.
|
||||
"""
|
||||
# We can't use the catalogue check value since it requires 8-bit
|
||||
# inputs, so we'll instead use an input of b"12345678".
|
||||
data = b"12345678"
|
||||
# Split data into individual bits. When input is reflected, we have
|
||||
# to reflect each byte first, then form the input words, then let
|
||||
# the CRC module reflect those words, to get the same effective input.
|
||||
bits = "".join(f"{x:08b}" for x in data)
|
||||
bits_r = "".join(f"{x:08b}"[::-1] for x in data)
|
||||
|
||||
for name in CRCS:
|
||||
for m in (1, 2, 4, 16, 32, 64):
|
||||
algo = getattr(catalog, name)
|
||||
crc = algo(data_width=m).create()
|
||||
# Use a SoftwareCRC with byte inputs to compute new checks.
|
||||
swcrc = algo(data_width=8)
|
||||
check = swcrc.compute(data)
|
||||
# Chunk input bits into m-bit words, reflecting if needed.
|
||||
if algo.reflect_input:
|
||||
d = [bits_r[i : i+m][::-1] for i in range(0, len(bits), m)]
|
||||
else:
|
||||
d = [bits[i : i+m] for i in range(0, len(bits), m)]
|
||||
words = [int(x, 2) for x in d]
|
||||
|
||||
def process():
|
||||
yield crc.start.eq(1)
|
||||
yield
|
||||
yield crc.start.eq(0)
|
||||
for word in words:
|
||||
yield crc.data.eq(word)
|
||||
yield crc.valid.eq(1)
|
||||
yield
|
||||
yield crc.valid.eq(0)
|
||||
yield
|
||||
self.assertEqual((yield crc.crc), check)
|
||||
|
||||
sim = Simulator(crc)
|
||||
sim.add_sync_process(process)
|
||||
sim.add_clock(1e-6)
|
||||
sim.run()
|
||||
|
||||
def test_crc_match(self):
|
||||
"""Verify match_detected output detects valid codewords."""
|
||||
for name in CRCS:
|
||||
algo = getattr(catalog, name)
|
||||
n = algo.crc_width
|
||||
m = 8 if n % 8 == 0 else 1
|
||||
crc = algo(data_width=m).create()
|
||||
check = CRC_CHECKS[name][0]
|
||||
|
||||
if m == 8:
|
||||
# For CRCs which are multiples of one byte wide, we can easily
|
||||
# append the correct checksum in bytes.
|
||||
check_b = check.to_bytes(n // 8, "little" if algo.reflect_output else "big")
|
||||
words = b"123456789" + check_b
|
||||
else:
|
||||
# For other CRC sizes, use single-bit input data.
|
||||
if algo.reflect_output:
|
||||
check_b = check.to_bytes((n + 7)//8, "little")
|
||||
if not algo.reflect_input:
|
||||
# For cross-endian CRCs, flip the CRC bits separately.
|
||||
check_b = bytearray(int(f"{x:08b}"[::-1], 2) for x in check_b)
|
||||
else:
|
||||
shift = 8 - (n % 8)
|
||||
check_b = (check << shift).to_bytes((n + 7)//8, "big")
|
||||
# No catalogue CRCs have ref_in but not ref_out.
|
||||
codeword = b"123456789" + check_b
|
||||
words = []
|
||||
for byte in codeword:
|
||||
if algo.reflect_input:
|
||||
words += [int(x) for x in f"{byte:08b}"[::-1]]
|
||||
else:
|
||||
words += [int(x) for x in f"{byte:08b}"]
|
||||
words = words[:72 + n]
|
||||
|
||||
def process():
|
||||
yield crc.start.eq(1)
|
||||
yield
|
||||
yield crc.start.eq(0)
|
||||
for word in words:
|
||||
yield crc.data.eq(word)
|
||||
yield crc.valid.eq(1)
|
||||
yield
|
||||
yield crc.valid.eq(0)
|
||||
yield
|
||||
self.assertTrue((yield crc.match_detected))
|
||||
|
||||
sim = Simulator(crc)
|
||||
sim.add_sync_process(process)
|
||||
sim.add_clock(1e-6)
|
||||
sim.run()
|
Loading…
Reference in a new issue