CRC (Cyclic Redundancy Check) is the most widely used error-detection mechanism in digital communication — from Ethernet frames to USB packets to SSD data integrity. This post explains how CRC works mathematically and shows how to use the free online CRC Calculator & RTL Generator to produce ready-to-simulate SystemVerilog code for your FPGA design.
What Is CRC?
CRC appends a checksum to a data block so the receiver can detect corruption. The transmitter computes a CRC value over the data and appends it; the receiver recomputes the CRC and compares. A mismatch means a transmission error occurred.
Why CRC Instead of a Simple Sum?
The simplest error-detection method is summing all bytes. The problem: if two bits flip simultaneously in opposing directions, the total sum is unchanged and the error goes undetected — especially with burst errors.
CRC is based on polynomial division over GF(2) and is guaranteed to detect:
- All single-bit errors
- All burst errors up to the CRC width (e.g., any 32-bit burst with CRC-32)
- Most longer random errors with very high probability
Mathematical Foundation
Polynomial Arithmetic over GF(2)
CRC treats a bit stream as a polynomial with binary coefficients. In GF(2):
- Addition = XOR (
1+1=0,1+0=1) - Multiplication = AND (
1×1=1,1×0=0) - Subtraction = XOR (same as addition)
The bit string 11010011 represents:
$$D(x) = x^7 + x^6 + x^4 + x^1 + x^0$$
CRC is the remainder when the data polynomial $D(x)$ is divided by a fixed generator polynomial $G(x)$:
$$\text{CRC} = D(x) \cdot x^r \bmod G(x)$$
where $r$ is the CRC width in bits.
Generator Polynomial
Each CRC standard defines its own generator polynomial. For CRC-32:
$$G(x) = 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$$
In hexadecimal (dropping the implicit leading $x^{32}$ term): 0x04C11DB7.
CRC Parameters Explained
These six parameters define the CRC calculation; protocol coverage and transmission order must also be specified:
| Parameter | Description | CRC-32 Value |
|---|---|---|
| Width | CRC output bit width | 32 |
| Poly | Generator polynomial (MSB implicit) | 0x04C11DB7 |
| Init | Initial value loaded into the CRC register | 0xFFFFFFFF |
| RefIn | Reflect (bit-reverse) each input byte before processing | true |
| RefOut | Reflect the final CRC register before output | true |
| XorOut | XOR mask applied to the final output | 0xFFFFFFFF |
Why RefIn / RefOut?
In serial hardware, data is often transmitted LSB-first. Setting RefIn=true reverses the bit order of each input byte before feeding it through the CRC shift register, aligning the hardware shift direction with the software calculation. RefOut=true reflects the final register value before outputting — required by standards like Ethernet that also process bits LSB-first.
Ethernet (CRC-32) uses RefIn=RefOut=true. CRC-16/IBM-3740 uses RefIn=RefOut=false. Getting these wrong produces a completely different result, so always verify against a known test vector.
Common CRC Standards
| Name | Width | Poly | Init | XorOut | RefIn | RefOut | Used In |
|---|---|---|---|---|---|---|---|
| CRC-32 | 32 | 04C11DB7 | FFFFFFFF | FFFFFFFF | ✓ | ✓ | Ethernet, ZIP, PNG |
| CRC-32C | 32 | 1EDC6F41 | FFFFFFFF | FFFFFFFF | ✓ | ✓ | iSCSI, SCTP |
| CRC-16/ARC | 16 | 8005 | 0000 | 0000 | ✓ | ✓ | ARC |
| CRC-16/IBM-3740 | 16 | 1021 | FFFF | 0000 | ✗ | ✗ | IBM-3740 (CCITT-FALSE) |
| CRC-16/MODBUS | 16 | 8005 | FFFF | 0000 | ✓ | ✓ | Modbus RTU |
| CRC-8 | 8 | 07 | 00 | 00 | ✗ | ✗ | SMBus PEC |
Using the Online Tool
👉 Open CRC Calculator & RTL Generator
Step 1 — Select a Preset
Click one of the preset buttons at the top (e.g., CRC-32 (Ethernet)). All parameters fill in automatically. For a non-standard CRC, click Custom and enter the Poly, Init, and XorOut values manually.
Step 2 — Enter Input Data
Three input modes are supported:
HEX mode (default) — enter bytes as hex tokens, read left-to-right:
31 32 33 34 35 36 37 38 39 ← "123456789" as ASCII hex bytes
A token longer than 2 hex digits is split into bytes from the left. Example: 78563412 → bytes [0x78, 0x56, 0x34, 0x12].
ASCII mode — type text directly:
123456789
Binary mode — 8-bit groups separated by spaces:
00110001 00110010 00110011
Step 3 — Calculate
Click Calculate. The result appears in HEX, Decimal, Binary, and Verilog literal format. Any value can be copied to clipboard with one click.
Verification: The CRC-32 of the ASCII string 123456789 must be 0xCBF43926. This is the reference check value for CRC-32/ISO-HDLC. The Self-Test section checks all six presets in JavaScript; it does not run an HDL simulator.
Step 4 — Generate RTL
Scroll to the RTL Generator card:
- Set Data Width — how many bits per clock your FPGA design processes (8 / 16 / 32 / 64)
- Module Name is auto-populated (e.g.,
crc32_w32) - Click ⚡ Generate RTL + Testbench
Two tabs appear: RTL (the module) and Testbench (self-checking simulation). Use 📋 Copy or ⬇ Download to save the .sv files.
Understanding the Generated RTL
The output module follows this structure:
| |
The Key Idea: Parallel CRC via GF(2) Matrix
A bit-serial CRC shift register processes one bit per clock. For FPGA designs that must handle 32 or 64 bits per clock, we derive a linear transformation matrix that maps the current CRC state $\mathbf{c}$ and input data $\mathbf{d}$ to the next state in a single combinational stage:
$$\mathbf{c}_{\text{next}} = \mathbf{A} \cdot \mathbf{c} \oplus \mathbf{B} \cdot \mathbf{d}$$
where $\mathbf{A}$ encodes which CRC bits feed each output bit, and $\mathbf{B}$ encodes which data bits feed each output bit. Since all matrix entries are 0 or 1, the matrix-vector product becomes a tree of XOR gates. The RTL generator pre-computes these matrices and unrolls each output bit equation — resulting in a single-cycle combinational stage regardless of data width.
Port Reference
| Port | Direction | Description |
|---|---|---|
clk | input | Clock, sampled on rising edge |
resetn | input | Active-low synchronous reset — loads Init value into crc_reg |
data_in | input | Input data word (Data Width bits wide) |
crc_out | output | Registered CRC state; valid one clock after each data_in |
crc_final | output | crc_out ^ XorOut; present only when XorOut ≠ 0 |
Processing a Continuous Stream
Apply successive data words without asserting reset between them. crc_final holds the running CRC one cycle after each word.
clk: __|‾|_|‾|_|‾|_|‾|_|‾|_
resetn: __|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|_
data_in: X | W0 | W1 | W2 | W3 | X
crc_final: X | X | C1 | C2 | C3 | FINAL
To start a new CRC frame, assert resetn for one clock, then deassert.
Running the Simulation
The generated testbench runs two self-checking tests:
| Test | What It Checks |
|---|---|
| Single word | CRC after processing one data word |
| 4-word chain | CRC after processing four consecutive words without reset |
Icarus Verilog (free)
| |
Vivado xsim
| |
Expected output:
============================================================
CRC RTL Builder — Testbench: crc32_w32
Algorithm : CRC-32 (Ethernet/802.3)
============================================================
PASS: Single word | 0x...
PASS: 4-word chain | 0x...
============================================================
2 PASSED 0 FAILED
ALL TESTS PASSED ✓
FAQ
Q: My result doesn’t match another CRC tool — why?
Check RefIn, RefOut, Init, and XorOut first. RefIn/RefOut differences alone will produce a completely different result. Use the Self-Test section to compare against six reference check values instantly.
Q: How do I choose Data Width?
Match the AXI-Stream tdata width of your design. 1GbE commonly uses 8 or 32 bits; 10GbE uses 64 bits; 100GbE up to 512 bits. Wider data width generates more XOR gates and the generated logic forms one combinational stage; timing closure is not guaranteed.
Q: Which output should I use — crc_out or crc_final?
If XorOut ≠ 0 (CRC-32, CRC-32C, etc.) use crc_final. If XorOut = 0 (CRC-16/ARC, CRC-8, etc.) crc_out is the final value and crc_final is not generated.
Q: Can I generate a custom-width CRC, like CRC-24?
The current interface supports CRC widths of 8, 16, and 32 bits. Custom changes the polynomial and other parameters within those widths; CRC-24 is not currently supported.
Wrapping Up
CRC is a critical block in any FPGA communication interface design, but the combination of parameters and the parallel-implementation math can be tricky to get right. The EasyFPGA CRC Calculator lets you validate parameters instantly against known test vectors and generate synthesizable, self-verifying SystemVerilog in seconds — no installation required.
Usage Terms and Verification Scope
Calculation and RTL/testbench generation remain free for personal learning on this website. The generated module is a basic datapath that consumes a full word every clock after synchronous reset. It has no enable/valid, frame-start, or partial-word handling. RefIn=true processes the lowest byte first; RefIn=false processes the highest byte first. Add and verify the controls required by your protocol. Timing closure depends on the device, data width, and implementation.
The browser Self-Test compares six reference check values and a JavaScript evaluation of the RTL equations at 8 bits/clock. It does not compile or simulate SystemVerilog. The generated testbench provides two smoke tests whose expected values are derived from the same matrix as the RTL; these do not replace independent reference-model testing. Run a simulator and verify frame boundaries, stalls, reset, and byte order before integrating a design.
For CRC principles, see XOR division and the interactive lab. For integration support or usage permission, use the contact page.
© 2026 EasyFPGA. All rights reserved.
The EasyFPGA-created explanations, code, and tools may be viewed and run on this website for personal learning. Except as permitted by law, copying, modification, redistribution, or incorporation into other products or services requires prior written permission from EasyFPGA. Public access does not grant an open-source license. Request permission through the contact page. Rights to external references remain with their respective owners. These terms apply to this updated version and do not retroactively change previously distributed versions.