CRC Generator (crc_generator_c)

Appends a trailing cyclic redundancy check (CRC) to sample data between two flush or discontinuity messages.

Design

On reception of a flush or discontinuity opcode message, a CRC will be generated for any sample data received since the last flush or discontinuity messages.

A CRC is an error-detecting algorithm commonly used to detect errors during the exchange of data. The CRC value is the remainder of a polynomial division algorithm on the input data stream.

An example of a common CRC type is CRC-8-WCDMA. This is used for error detection in mobile networks. It has a polynomial shown by (21), which can also be defined as 0x9B.

(21)\[x^8+x^7+x^4+x^3+x+1\]

Using the CRC-8-WCDMA example the following output is produced from the provided input. Note the input is an entire message that is four bytes in length. Also the left most byte is input into the CRC generator component first.

Input: 0x01, 0x02, 0x03, 0x04

Output: 0x01, 0x02, 0x03, 0x04, 0xD6

Compared to the input the output message size has increased by one byte to five bytes due to the addition of a trailing CRC. The appended CRC is 0xD6.

The polynomial_taps property sets the divisor of the polynomial long division algorithm. It is set at build time. The size of the polynomial multiplied by the data width, eight, gives the total number of shift registers used in the HDL implementation.

The seed property defines the initial value of the CRC at the start of a message. It is settable during run time.

Depending on the application the input data or CRC result may need to be reflected for a different endianness. Properties input_reflect and output_reflect provide the option to enable or disable this. They are set at build time.

Some CRC’s require a final XOR on the CRC result. The final XOR value is set by the property final_xor. It is settable during run time.

Interface

<?xml version="1.0"?>
<componentspec>
  <property name="polynomial_taps" type="uchar" arraylength="64" writable="false" parameter="true" default="16,15,2"
    description="Polynomial taps of the CRC used."/>
  <property name="input_reflect" type="bool" writable="false" parameter="true" default="false"
    description="True reverses the bit order of the input data, False keeps the order the same."/>
  <property name="output_reflect" type="bool" writable="false" parameter="true" default="false"
    description="False is CRC most significant bit first and true is CRC least significant bit first."/>
  <property name="seed" type="ulonglong" writable="true" default="0" description="Initial seed in CRC generator."/>
  <property name="final_xor" type="ulonglong" writable="true" default="0" description="Value to XOR the CRC result with."/>
  <port name="input" producer="false" protocol="char_timed_sample-prot"/>
  <port name="output" producer="true" protocol="char_timed_sample-prot"/>
</componentspec>

Ports

Inputs:

  • input: Primary input samples port.

    • Protocol: char_timed_sample-prot

    • Optional: False

Outputs:

  • output: Primary output samples port.

    • Protocol: char_timed_sample-prot

    • Optional: False

Opcode Handling

Discontinuity and flush opcode messages mark the end of a message and cause the component to append a CRC to any sample data received since the previous discontinuity or flush message. The component applies backpressure whilst outputting the CRC. When the component has finished generating the CRC it is reset, the discontinuity or flush opcode is forwarded to the output, and backpressure is removed.

All other message opcode types are passed through this component without any effect.

Properties

  • polynomial_taps: Polynomial taps of the CRC used. An array of up to 64 unsigned characters, meaning a maximum of 64 taps can be specified. If the polynomial is \(x^8+x^2+x+1\) then polynomial_taps should be set to “8,2,1”. There is no need to specify the \(x^0\) term, this is implied.

    • Type: uchar

      • Array dimensions: ['64']

    • Access:

      • Parameter: True

      • Writable: False

      • Initial: False

      • Volatile: False

    • Default value: 16,15,2

  • input_reflect: True reverses the bit order of the input data, False keeps the order the same.

    • Type: bool

    • Access:

      • Parameter: True

      • Writable: False

      • Initial: False

      • Volatile: False

    • Default value: false

  • output_reflect: False is CRC most significant bit first and true is CRC least significant bit first.

    • Type: bool

    • Access:

      • Parameter: True

      • Writable: False

      • Initial: False

      • Volatile: False

    • Default value: false

  • seed: Initial seed in CRC generator.

    • Type: ulonglong

    • Access:

      • Parameter: False

      • Writable: True

      • Initial: False

      • Volatile: False

    • Default value: 0

  • final_xor: Value to XOR the CRC result with.

    • Type: ulonglong

    • Access:

      • Parameter: False

      • Writable: True

      • Initial: False

      • Volatile: False

    • Default value: 0

A table listing the default polynomials the component is built for is shown below.

Polynomial

polynomial_taps

output_reflect

\(x^8 + x^2 + x + 1\)

8,2,1

true and
false

\(x^8 + x^4 + x^3 + x^2 + 1\)

8,4,3,2

true and
false

\(x^8 + x^5 + x^3 + x^2 + x + 1\)

8,5,3,2,1

false

\(x^8 + x^5 + x^4 + 1\)

8,5,4

true

\(x^8 + x^5 + x^4 + x^3 + 1\)

8,5,4,3

true

\(x^8 + x^7 + x^4 + x^3 + x + 1\)

8,7,4,3,1

true

\(x^8 + x^7 + x^6 + x^4 + x^2 + 1\)

8,7,6,4,2

false

\(x^{16} + x^{10} + x^8 + x^7 + x^3 + 1\)

16,10,8,7,3

false

\(x^{16} + x^{12} + x^5 + 1\)

16,12,5

true and
false
\(x^{16} + x^{13} + x^{12} + x^{11} + x^{10} + x^8 +\)
\(x^6 + x^5 + x^2 + 1\)
16,13,12,11,10,8,
6,5,2
true and
false

\(x^{16} + x^{15} + x^2 + 1\)

16,15,2

true and
false
\(x^{16} + x^{15} + x^{11} + x^9 + x^8 + x^7 +\)
\(x^5 + x^4 + x^2 + x + 1\)
16,15,11,9,8,7,
5,4,2,1

false

\(x^{16} + x^{15} + x^{13} + x^7 + x^4 + x^2 +\)
\(x + 1\)
16,15,13,7,4,2,
1

false

\(x^{16} + x^{15} + x^{14} + x^{11} + x^6 + x^5 +\)
\(x^2 + x + 1\)
16,15,14,11,6,5,
2,1

false

\(x^{32} + x ^7 + x^5 + x^3 + x^2 + x + 1\)

32,7,5,3,2,1

false

\(x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} +\)
\(x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 +\)
\(x^2 + x + 1\)
32,26,23,22,16,12,
11,10,8,7,5,4,
2,1
true and
false
\(x^{32} + x^{28} + x^{27} + x^{26} + x^{25} + x^{23} +\)
\(x^{22} + x^{20} + x^{19} + x^{18} + x^{14} + x^{13} +\)
\(x^{11} + x^{10} + x^9 + x^8 + x^6 + 1\)
32,28,27,26,25,23,
22,20,19,18,14,13,
11,10,9,8,6

true

\(x^{32} + x^{31} + x^{24} + x^{22} + x^{16} + x^{14} +\)
\(+ x^8 + x^7 + x^5 + x^3 + x + 1\)
32,31,24,22,16,14,
8,7,5,3,1

false

\(x^{32} + x^{31} + x^{29} + x^{27} + x^{21} + x^{20} +\)
\(x^{17} + x^{16} + x^{15} + x^{12} + x^{11} + x^5 +\)
\(x^3 + x + 1\)
32,31,29,27,21,20,
17,16,15,12,11,5,
3,1

true

\(x^{64} + x^4 + x^3 + x + 1\)

64,4,3,1

true

\(x^{64} + x^{62} + x^{57} + x^{55} + x^{54} + x^{53} +\)
\(x^{52} + x^{47} + x^{46} + x^{45} + x^{40} + x^{39} +\)
\(x^{38} + x^{37} + x^{35} + x^{33} + x^{32} + x^{31} +\)
\(x^{29} + x^{27} + x^{24} + x^{23} + x^{22} + x^{21} +\)
\(x^{19} + x^{17} + x^{13} + x^{12} + x^{10} + x^9 +\)
\(x^7 + x^4 + x + 1\)
64,62,57,55,54,53,
52,47,46,45,40,39,
38,37,35,33,32,31,
29,27,24,23,22,21,
19,17,13,12,10,9,
7,4,1
true and
false

Implementations

Example Application

<?xml version="1.0"?>
<application done="file_write">
  <instance component="ocpi.core.file_read" connect="crc_generator_c">
    <property name="filename" value="input.bin"/>
  </instance>
  <instance component="ocpi.comp.sdr.communication.crc_generator_c" connect="file_write">
    <property name="polynomial_taps" value="16,15,2"/>
    <property name="seed" value="0"/>
    <property name="input_reflect" value="false"/>
    <property name="output_reflect" value="false"/>
    <property name="final_xor" value="0"/>
  </instance>
  <instance component="ocpi.core.file_write">
    <property name="filename" value="output.bin"/>
  </instance>
</application>

Dependencies

The dependencies to other elements in OpenCPI are:

There is also a dependency on:

  • ieee.std_logic_1164

  • ieee.numeric_std

  • ieee.math_real

Limitations

Limitations of crc_generator_c are:

  • Only CRC sizes of 8, 16, 24, 32, 40, 48, 56, and 64 are supported.

  • The component uses the crc_parallel primitive which calculates the CRC in a single clock cycle. For larger CRC lengths this can require a lengthy logic path to evaluate within a single clock cycle. This may limit the maximum clock speed that a design can run at.

Testing

Tested platforms: None

Component testing not completed.