olo_base_crc¶
Status Information¶
VHDL Source: olo_base_crc
Description¶
This component is a CRC checksum generator. It can be used to generate CRC checksums to send together with data (TX side) or to calculate the CRC checksum of received data and compare it to the CRC received (RX side).
olo_base_crc can take one input data word per clock cycle. One CRC is produced per packet - the Out_Valid signal is presented to the output after In_Last was received. Although Out_Valid is asserted only upon the In_Last being received, the output Out_Crc is updated exactly one clock cycle after an input word being received. This allows for special applications where the CRC has to be checked after every data-word.
The component is highly configurable in order to allow calculating CRC checksums for all known standard protocols without any external logic. Regarding the notation of parametrization, the website crccalc.com is taken as reference. On this website many commonly used CRCs are listed.
Generics¶
| Name | Type | Default | Description |
|---|---|---|---|
| DataWidth_g | positive | - | Input data width |
| Polynomial_g | std_logic_vector | - | CRC Polynomial according to the notation in crccalc.com - which matches the comon-sense. MSB left. For good readability use hex notation (e.g. x"D5") Width of the CRC is the number of bits in the Polynomial. For details, see Architecture |
| InitialValue_g | std_logic_vector | all '0' | Initial value to load into the LFSR before the first data word arrives. MSB left. For good readability use hex notation (e.g. x"D5") |
| BitOrder_g | string | "MSB_FIRST" | The input can be processed "MSB_FIRST" or "LSB_FIRST". "MSB_FIRST" - Most significant bit is shifted into LFSR first "LSB_FIRST" - Least significant bit is shifted into LFSR first |
| ByteOrder_g | string | "NONE" | This generic allows byte-wise processing of the input if required. "NONE" - No byte-wise processing, the whole input is interpreted as one word "MSB_FIRST" - Most significant byte of the input is shifted into the LFSR first. "LSB_FIRST" - Least significant byte of the input is shifted into the LFSR first. For any other values than "NONE" the setting of BitOrder_g is applied to the ordering of bits within each byte. Note: Other values than "NONE" are only allowed if DataWidth_g is a multiple of 8 |
| BitflipOutput_g | boolean | false | If set to true the LFSR content is bit-flipped (MSB to LSB and vice-versa) for output through Out_Crc. |
| XorOutput_g | std_logic_vector | all '0' | XOR mask to apply to the output. This is required for certain standards according to crccalc.com. The XOR mask is applied after bitflip in case of BitFlipOutput_g=true. |
Note: For cases where no exact protocol specification must be followed (for user defined protocols) it is suggested to leave the following generics on their default value. These generics are only used to match exact protocol specifications.
- XorOutput_g
- BitflipOutput_g
- ByteOrder_g
- BitOrder_g
- InitialValue_g
Interfaces¶
Control¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Clk | in | 1 | - | Clock |
| Rst | in | 1 | - | Reset input (high-active, synchronous to Clk) |
Input Data¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| In_Data | in | DataWidth_g | - | Input data |
| In_Valid | in | 1 | '1' | AXI4-Stream handshaking signal for In_Data |
| In_Ready | out | 1 | - | AXI4-Stream handshaking signal for In_Data |
| In_Last | in | 1 | '0' | AXI4-Stream packet end signaling for In_Data |
| In_First | in | 1 | '0' | In case a packet is aborted/finished without a In_Last this bit can be pulled high on the first In_Data word of the next packet to signal the start of a new packet. |
| In_Be | in | DataWidth_g/8 | All '1' | Byte-enables Ignored if DataWidth_g mod 8 /= 0 May be de-asserted only when In_Last = '1' When de-asserted, it must follow the LSB-first convention: the LSB bit must always be asserted and all asserted bits must be contiguous (no gaps). |
Output Data¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Out_Crc | out | width(Polynomial_g) | - | Output CRC checksum |
| Out_Valid | out | 1 | - | AXI4-Stream handshaking signal for Out_Data |
| Out_Ready | in | 1 | '1' | AXI4-Stream handshaking signal for Out_Data |
Architecture¶
For the following documentation, the abbreviation LFSR stands for Linear Feedback Shift Register, a hardware optimized CRC calculation algorithm.
The figure below shows the overall architecture of olo_base_crc. It also nicely shows the order of operations. Note that flow-control is not depicted for simplicity reasons.
The handling of BitOrder_g and ByteOrder_g might be non-straightforward to understand. The table below lists all combinations.
| In_Data | BitOrder_g | ByteOrder_g | LFSR Input (first bit left) |
|---|---|---|---|
| "0001_0011_0111_1111" | "MSB_FIRST" | "NONE" / "MSB_FIRST" | 0001 0011 0111 1111 |
| "0001_0011_0111_1111" | "LSB_FIRST" | "NONE" / "LSB_FIRST" | 1111 1110 1100 1000 |
| "0001_0011_0111_1111" | "MSB_FIRST" | "LSB_FIRST" | 0111 1111 0001 0011 |
| "0001_0011_0111_1111" | "LSB_FIRST" | "MSB_FIRST" | 1100 1000 1111 1110 |
The handling of BitflipOutput_g and XorOutput_g might be non-straightforward to understand. The table below lists all combinations.
| LFSR Content | BitflipOutput_g | XorOutput_g | Out_Crc |
|---|---|---|---|
| "1010_0011" | true | 16#00# | "1100_0101" |
| "1010_0011" | false | 16#00# | "1010_0011" |
| "1010_0011" | true | 16#0F# | "1100_1010" |
| "1010_0011" | false | 16#0F# | "1010_1100" |
Below figure shows how CRC polynomials are represented in Polynomial_g and how the LFSR itself exactly is implemented. The figure is drawn as if only one bit per clock cycle is processed but in reality multiple bits are processed - hence the figure does not depict the actual implementation but the functionality.
Below table lists the settings to be used for a set of standard CRCs according to different protocol specifications. More standard CRCs can be found on crccalc.com. All the CRCs listed in below table are also present in crccalc.com and hence the mapping of values from crccalc.com to olo_base_crc generics is clarified by the table.
| CRC Standard | Polynomial_g | InitialValue_g | BitOrder_g | BitflipOutput_g | XorOutput_g |
|---|---|---|---|---|---|
| CRC-8/DVB-S2 | 0xD5 | 0x00 | "MSB_FIRST" | false | 0x00 |
| CRC-8/AUTOSAR | 0x2F | 0xFF | "MSB_FIRST" | false | 0xFF |
| CRC-8/BLUETOOTH | 0xA7 | 0x00 | "LSB_FIRST" | true | 0x00 |
| CRC-16/DECT-R | 0x0589 | 0x0000 | "MSB_FIRST" | false | 0x0001 |
| CRC-16/DDS-110 | 0x8005 | 0x800D | "MSB_FIRST" | false | 0x0000 |
Below figure depicts the handshaking, the usage of In_Last/In_First as well as Out_Crc being valid one clock cycle after every data input.

The following points are worth mentioning:
- The CRC for the example is CRC-8/DVB-S2
- Three identical packets are processed (data 0x11, 0x12, 0x13)
- Out_Crc is updated exactly one clock cycle after the input data being transferred
- The first packet shows backpressure (propagation of Out_Ready to In_Ready)
- The second packet is not terminated by In_Last and the start of the third packet is indicated by In_First
Byte enables¶
In_Be MUST follow the Trailing-Only Byte-Enable convention. If it doesn't it will result in simulation errors and undefined behavior in synthesis.
For example, if In_Be is 4 bits wide, the valid values on the last data-beat (In_Last = '1') are:
- In_Be = "1111"
- In_Be = "0111"
- In_Be = "0011"
- In_Be = "0001"
The example below shows a 16 bit input data bus. For simplicity, the signals In_Ready, Out_Ready and In_First are not shown, but they are fully supported in the implementation. The olo_base_crc in this example uses "MSB_FIRST" byte order and the CRC-8/DVB-S2 algorithm.
Three packets are processed:
- Packet1: 1 byte (CRC proccesses byte 0x11)
- Packet2: 2 bytes (CRC proccesses 0x11, then 0x22)
- Packet3: 3 bytes (CRC proccesses 0x11, then 0x22 and finally 0x33)

Note: olo_base_crc is configured with ByteOrder_g = "MSB_FIRST". Even with this setting, In_Be still follows the Trailing-Only Byte-Enable convention. On the last data beat, the byte-enable is not In_Be = "10", but In_Be = "01". With "MSB_FIRST" the most significant byte out of the enabled ones (according to In_Be) is processed first.