Skip to content

Commit 18460d0

Browse files
committed
Update CRC RFC to address review comments
1 parent 17de834 commit 18460d0

File tree

1 file changed

+40
-35
lines changed

1 file changed

+40
-35
lines changed

text/0006-stdlib-crc.md

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,16 @@ For a list of parameters to use for standard CRCs, refer to:
6262
remove the leading `1`.
6363

6464
The CRC algorithms described in the [reveng] catalogue are also available
65-
in the Amaranth standard library in the `crc.Catalog` class.
65+
in the Amaranth standard library in the `crc.catalog` module.
6666

6767
[reveng]: https://reveng.sourceforge.io/crc-catalogue/all.htm
6868
[crcmod]: http://crcmod.sourceforge.net/crcmod.predefined.html
6969
[CRC Zoo]: https://users.ece.cmu.edu/~koopman/crc/
7070

71-
In Amaranth, the `crc.Parameters` class holds the parameters that describe a
71+
In Amaranth, the `crc.Algorithm` class holds the parameters that describe a
7272
CRC algorithm:
7373

7474
* `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
7775
* `polynomial`: the generator polynomial of the CRC, excluding an implicit
7876
leading 1 for the "x^n" term
7977
* `initial_crc`: the initial value of the CRC, loaded when computation of a
@@ -84,26 +82,33 @@ CRC algorithm:
8482
least-significant bit becomes the most-significant bit of output
8583
* `xor_output`: a value to XOR the output with
8684

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:
85+
The `crc.Algorithm` class may be constructed manually, but for many
86+
commonly used CRC algorithms a predefined instance is available in
87+
the `crc.catalog` module.
88+
89+
To fully define a CRC computation, the width of input data words to the CRC
90+
must also be specified. This is commonly 8 for processing byte-wise data,
91+
but can be any length greater than 0. The combination of a `crc.Algorithm`
92+
and the `data_width` makes a `crc.Parameters` instance, for example:
9193

9294
```python
9395
from amaranth.lib import crc
94-
params1 = crc.Parameters(8, 8, 0x2f, 0xff, False, False, 0xff)
95-
params2 = crc.Catalog.CRC8_AUTOSAR(data_width=8)
96+
algo = crc.Algorithm(crc_width=8, polynomial=0x2f, initial_crc=0xff,
97+
reflect_input=False, reflect_output=False,
98+
xor_output=0xff)
99+
params1 = algo(data_width=8)
100+
params2 = crc.catalog.CRC8_AUTOSAR(data_width=8)
96101
```
97102

98103
If not specified, the data width defaults to 8 bits.
99104

100-
The `crc.Parameters` class can be used to compute CRCs in software using its
105+
The `crc.Parameters` class can be used to compute CRCs in software with its
101106
`compute()` method, which is passed an iterable of integer data words and
102107
returns the resulting CRC value.
103108

104109
```python
105110
from amaranth.lib import crc
106-
params = crc.Parameters(8, 8, 0x2f, 0xff, False, False, 0xff)
111+
params = crc.catalog.CRC8_AUTOSAR()
107112
assert params.compute(b"123456789") == 0xdf
108113
```
109114

@@ -112,14 +117,17 @@ or manually construct a `crc.Processor`:
112117

113118
```python
114119
from amaranth.lib import crc
115-
params = crc.Parameters(8, 8, 0x2f, 0xff, False, False, 0xff)
120+
algo = crc.Algorithm(crc_width=8, polynomial=0x2f, initial_crc=0xff,
121+
reflect_input=False, reflect_output=False,
122+
xor_output=0xff)
123+
params = algo(data_width=8)
116124
crc1 = m.submodules.crc1 = crc.Processor(params)
117125
crc2 = m.submodules.crc2 = crc.Catalog.CRC8_AUTOSAR().create()
118126
```
119127

120-
The `crc.Processor` module begins computation of a new CRC whenever its `first`
128+
The `crc.Processor` module begins computation of a new CRC whenever its `start`
121129
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
130+
which may occur in the same clock cycle as `start`. The updated CRC value is
123131
available on the `crc` output on the clock cycle after `valid`.
124132

125133
With the data width set to 1, a traditional bit-serial CRC is implemented
@@ -129,7 +137,7 @@ parallel.
129137

130138
The `match_detected` output signal may be used to validate data that contains a
131139
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
140+
the data processed since `start`, the CRC register will always contain a fixed
133141
value which can be computed in advance, and the `match_detected` output
134142
indicates whether the CRC register currently contains this value.
135143

@@ -138,33 +146,31 @@ indicates whether the CRC register currently contains this value.
138146

139147
The proposed new interface is:
140148

141-
* A `crc.Parameters` class which holds the parameters for a CRC algorithm,
149+
* A `crc.Algorithm` class which holds the parameters for a CRC algorithm,
142150
all of which are passed to the constructor:
143151
* `crc_width`: bit width of the CRC register
144-
* `data_width`: bit width of input data words
145152
* `polynomial`: generator polynomial for CRC algorithm
146153
* `initial_crc`: initial value of CRC at start of computation
147154
* `reflect_input`: if True, input words are bit-reversed
148155
* `reflect_output`: if True, output values are bit-reversed
149156
* `xor_output`: value to XOR the CRC value with at output
150-
* The class has the following methods:
157+
* `crc.Algorithm` implements `__call__(data_width=8)` which is used to create
158+
a `crc.Parameters` instance with the specified data width.
159+
* A `crc.Parameters` class which is constructed using a `crc.Algorithm` and
160+
a `data_width`.
161+
* `crc.Parameters` has the following methods:
151162
* `compute(data)` performs a software CRC computation on `data`, an
152163
iterable of input data words, and returns the CRC value
153164
* `create()` returns a `crc.Processor` instance preconfigured to use
154165
these parameters
155166
* `residue()` returns the residue value for these parameters, which is
156167
the value left in the CRC register after processing an entire valid
157168
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
169+
* `algorithm()` returns an `crc.Algorithm` with the same settings as
170+
this `crc.Parameters` instance
166171
* A `crc.Processor` class which inherits from `Elaboratable` and implements
167172
the hardware generator
173+
* A `crc.catalog` module which contains instances of `crc.Algorithm`
168174

169175
The hardware implementation uses the property that CRCs are linear, and so the
170176
new value of any bit of the CRC register can be found as a linear combination
@@ -229,18 +235,13 @@ computations.
229235
# Unresolved questions
230236
[unresolved-questions]: #unresolved-questions
231237

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?
238+
- No outstanding unresolved questions.
238239

239240
# Future possibilities
240241
[future-possibilities]: #future-possibilities
241242

242-
- The data interface uses `first`, `data`, and `valid` signals.
243-
Eventually, this should be replaced with a Stream, once they are finalised.
243+
- The data interface uses `start`, `data`, and `valid` signals.
244+
Eventually, this could be replaced with a Stream, once they are finalised.
244245

245246
- Currently the entire input data word must be valid together; there is no
246247
support for masking some bits off. In particular, such a feature could be
@@ -249,3 +250,7 @@ computations.
249250
FCS must be computed over individual bytes. However, the implementation
250251
complexity is high, the use cases seem more niche, and such a feature could
251252
be added in a backwards-compatible later revision.
253+
254+
- The software CRC computation only supports computing over an entire
255+
set of data. It would be possible to offer an API to permit incremental
256+
updates and finalisation.

0 commit comments

Comments
 (0)