@@ -24,76 +24,161 @@ See the [Wikipedia page on CRCs] for more background and use cases.
2424# Guide-level explanation
2525[ guide-level-explanation ] : #guide-level-explanation
2626
27- The standard library includes a generator for a cyclic redundancy check (CRC)
28- module, which can be used to compute and/or validate most common CRCs used by
29- transmission and storage protocols.
30-
31- There are many variations on CRCs in use, but they can almost all be described
32- by the following parameters:
33-
34- * The bit width of the checksum, commonly (but not always) a power of 2
35- * The generator polynomial
36- * The initial value of the CRC register
37- * Whether to process input words least- or most-significant-bit first
27+ The Amaranth standard library includes a generator for a cyclic redundancy
28+ check (CRC) module, which can be used to compute and/or validate most common
29+ CRCs used by transmission and storage protocols.
30+
31+ There are many different CRC algorithms in use, but they can almost all be
32+ described by the following parameters:
33+
34+ * The bit width of the CRC, commonly (but not always) a power of 2,
35+ * The generator polynomial, represented as an integer where each bit is a 0 or
36+ 1 term in a binary-valued polynomial with as many terms as the CRC width,
37+ * The initial value of the CRC register, commonly non-zero to allow detection
38+ of additional 0-valued data words at the start of a message,
39+ * Whether to process input words least- or most-significant-bit first,
40+ allowing the CRC processing order to match the transmission or storage order
41+ of the data bits,
3842* Whether to flip the final output so that its least-significant-bit becomes
39- the most-significant bit
40- * What value, if any, to XOR the output bits with before using the CRC value
43+ the most-significant bit, set for the same reason as reflecting the input
44+ when the CRC value will also be transmitted or stored with a certain bit
45+ order,
46+ * What value, if any, to XOR the output bits with before using the CRC value,
47+ often used to invert all bits of the output.
4148
4249This set of parameters is commonly known as the Williams or Rocksoft model. For
4350more information, refer to [ "A Painless Guide to CRC Error Detection Algorithms"] .
4451
4552[ "A Painless Guide to CRC Error Detection Algorithms" ] : http://www.ross.net/crc/download/crc_v3.txt
4653
47- The generator in the Amaranth standard library computes CRCs from an input
48- data stream of configurable width, and can therefore be use for both validating
49- existing CRCs and creating new ones. It can handle any CRC parameterised by
50- the Williams model above.
51-
5254For a list of parameters to use for standard CRCs, refer to:
5355
5456* [ reveng] 's catalogue, which uses the same parameterisation
55- * [ crcmod] 's predefined list, but removing the leading ` 1 ` from the
56- polynomials, and where ` Reversed ` is ` True ` , set both ` ref_in ` ** and**
57+ * [ crcmod] 's predefined list, but remove the leading ` 1 ` from the
58+ polynomials, XOR the "Init-value" with "XOR-out" to obtain ` initial_crc ` ,
59+ and where ` Reversed ` is ` True ` , set both ` ref_in ` ** and**
5760 ` ref_out ` to ` True ` .
5861* [ CRC Zoo] , which only lists polynomials; use the "explicit +1" form but
5962 remove the leading ` 1 ` .
6063
64+ The CRC algorithms described in the [ reveng] catalogue are also available
65+ in the Amaranth standard library in the ` crc.Catalog ` class.
66+
6167[ reveng ] : https://reveng.sourceforge.io/crc-catalogue/all.htm
6268[ crcmod ] : http://crcmod.sourceforge.net/crcmod.predefined.html
6369[ CRC Zoo ] : https://users.ece.cmu.edu/~koopman/crc/
6470
65- The computed CRC value is updated on any clock cycle where the ` valid ` input
66- is asserted, with the updated value available on the ` crc ` output on the
67- subsequent clock cycle. The latency is one cycle, and the throughput is
68- one data word per clock cycle.
71+ In Amaranth, the ` crc.Parameters ` class holds the parameters that describe a
72+ CRC algorithm:
73+
74+ * ` crc_width ` : the bit width of the CRC
75+ * ` data_width ` : the width of the input data words the CRC is computed over;
76+ commonly 8 for processing byte-wise data but can be any length greater than 0
77+ * ` polynomial ` : the generator polynomial of the CRC, excluding an implicit
78+ leading 1 for the "x^n" term
79+ * ` initial_crc ` : the initial value of the CRC, loaded when computation of a
80+ new CRC begins
81+ * ` reflect_input ` : if True, input words are bit-reversed so that the least
82+ significant bit is processed first
83+ * ` reflect_output ` : if True, the final output is bit-reversed so that its
84+ least-significant bit becomes the most-significant bit of output
85+ * ` xor_output ` : a value to XOR the output with
86+
87+ The ` crc.Parameters ` class may be constructed manually, or via a
88+ ` crc.Predefined ` entry in ` crc.Catalog ` , which contains many commonly
89+ used CRC algorithms. The data width is not part of the ` crc.Predefined `
90+ class, so it must be specified to create a ` crc.Parameters ` , for example:
91+
92+ ``` python
93+ from amaranth.lib import crc
94+ params1 = crc.Parameters(8 , 8 , 0x 2f , 0x ff , False , False , 0x ff )
95+ params2 = crc.Catalog.CRC8_AUTOSAR(data_width = 8 )
96+ ```
97+
98+ If not specified, the data width defaults to 8 bits.
99+
100+ The ` crc.Parameters ` class can be used to compute CRCs in software using its
101+ ` compute() ` method, which is passed an iterable of integer data words and
102+ returns the resulting CRC value.
103+
104+ ``` python
105+ from amaranth.lib import crc
106+ params = crc.Parameters(8 , 8 , 0x 2f , 0x ff , False , False , 0x ff )
107+ assert params.compute(b " 123456789" ) == 0x df
108+ ```
109+
110+ To generate a hardware CRC module, either call ` create() ` on ` crc.Parameters `
111+ or manually construct a ` crc.Processor ` :
112+
113+ ``` python
114+ from amaranth.lib import crc
115+ params = crc.Parameters(8 , 8 , 0x 2f , 0x ff , False , False , 0x ff )
116+ crc1 = m.submodules.crc1 = crc.Processor(params)
117+ crc2 = m.submodules.crc2 = crc.Catalog.CRC8_AUTOSAR().create()
118+ ```
119+
120+ The ` crc.Processor ` module begins computation of a new CRC whenever its ` first `
121+ input is asserted. Input on ` data ` is processed whenever ` valid ` is asserted,
122+ which may occur in the same clock cycle as ` first ` . The updated CRC value is
123+ available on the ` crc ` output on the clock cycle after ` valid ` .
69124
70125With the data width set to 1, a traditional bit-serial CRC is implemented
71126for the given polynomial in a Galois-type shift register. For larger values
72127of data width, a similar architecture computes every new bit of the CRC in
73128parallel.
74129
75- The ` match ` output signal may be used to validate data that contains a trailing
76- CRC. If the most recently processed word(s) form a valid CRC for all the data
77- processed since reset, the CRC register will always contain a fixed value which
78- can be computed in advance, and the ` match ` output indicates whether the CRC
79- register currently contains this value.
130+ The ` match_detected ` output signal may be used to validate data that contains a
131+ trailing CRC. If the most recently processed word(s) form a valid CRC for all
132+ the data processed since reset, the CRC register will always contain a fixed
133+ value which can be computed in advance, and the ` match_detected ` output
134+ indicates whether the CRC register currently contains this value.
80135
81136# Reference-level explanation
82137[ reference-level-explanation ] : #reference-level-explanation
83138
139+ The proposed new interface is:
140+
141+ * A ` crc.Parameters ` class which holds the parameters for a CRC algorithm,
142+ all of which are passed to the constructor:
143+ * ` crc_width ` : bit width of the CRC register
144+ * ` data_width ` : bit width of input data words
145+ * ` polynomial ` : generator polynomial for CRC algorithm
146+ * ` initial_crc ` : initial value of CRC at start of computation
147+ * ` reflect_input ` : if True, input words are bit-reversed
148+ * ` reflect_output ` : if True, output values are bit-reversed
149+ * ` xor_output ` : value to XOR the CRC value with at output
150+ * The class has the following methods:
151+ * ` compute(data) ` performs a software CRC computation on ` data ` , an
152+ iterable of input data words, and returns the CRC value
153+ * ` create() ` returns a ` crc.Processor ` instance preconfigured to use
154+ these parameters
155+ * ` residue() ` returns the residue value for these parameters, which is
156+ the value left in the CRC register after processing an entire valid
157+ codeword (data followed by its own valid CRC)
158+ * ` check() ` returns the CRC computation of the ASCII string "123456789",
159+ a defacto standard for validating CRC correctness
160+ * A ` crc.Predefined ` class which is constructed using all the parameters of
161+ ` crc.Parameters ` except ` data_width ` , which is application-specific. This
162+ class implements ` __call__(data_width=8) ` which is used to create a
163+ ` crc.Parameters ` with the specified data width
164+ * A ` crc.Catalog ` class which contains instances of ` crc.Predefined ` as
165+ class attributes
166+ * A ` crc.Processor ` class which inherits from ` Elaboratable ` and implements
167+ the hardware generator
168+
169+ The hardware implementation uses the property that CRCs are linear, and so the
170+ new value of any bit of the CRC register can be found as a linear combination
171+ of the current state and all the input bits. By expressing the CRC computation
172+ as a linear system like this, we can then determine the boolean equation used
173+ to update each bit of the CRC in parallel. A software CRC calculator is
174+ implemented in Python in order to find these logic equations.
175+
84176The proposed CRC generator is already implemented and available in [ PR 681] .
85177The docstrings and comments in it should explain its operation to a suitably
86178technical level of detail.
87179
88180[ PR 681 ] : https://github.com/amaranth-lang/amaranth/pull/681
89181
90- The proposed implementation uses the fact that CRCs are a linear calculation,
91- and so the new value of any bit of the CRC register can be found as a linear
92- combination of the current state and all the input bits. By expressing the CRC
93- computation as a linear system like this, we can then determine the logic
94- equation used to update each bit of the CRC in parallel. A software CRC
95- calculator is implemented in Python in order to find these logic equations.
96-
97182# Drawbacks
98183[ drawbacks ] : #drawbacks
99184
@@ -144,21 +229,18 @@ computations.
144229# Unresolved questions
145230[ unresolved-questions ] : #unresolved-questions
146231
147- - There is a ` reset ` signal to reset the CRC state to its initial value.
148- In practice, users could replace this with a ` ResetInserter ` wrapper.
149- Since all users will need this signal, it seems easier to include it
150- directly in the module interface.
151-
152- - We could include a number of standard CRC parameters directly in the standard
153- library, to make using them more convenient. I don't know what the preferred
154- interface for this would be, perhaps just a Python module with some
155- constants?
232+ - Currently the design uses a ` first ` signal to signal the beginning of a new
233+ CRC computation (previously called ` reset ` ). Requiring that it may be
234+ asserted simultaneously with the first valid data word of the new CRC adds
235+ muxes to the design that would not be needed if ` first ` and ` valid ` cannot
236+ be asserted together. Is this a worthwhile tradeoff, or is there a way to
237+ avoid the extra muxes?
156238
157239# Future possibilities
158240[ future-possibilities ] : #future-possibilities
159241
160- - The data interface uses a ` data ` and ` valid ` signal. Eventually, this should
161- be replaced with a Stream, once they are finalised.
242+ - The data interface uses ` first ` , ` data ` , and ` valid ` signals.
243+ Eventually, this should be replaced with a Stream, once they are finalised.
162244
163245- Currently the entire input data word must be valid together; there is no
164246 support for masking some bits off. In particular, such a feature could be
0 commit comments