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:

ParameterDescriptionCRC-32 Value
WidthCRC output bit width32
PolyGenerator polynomial (MSB implicit)0x04C11DB7
InitInitial value loaded into the CRC register0xFFFFFFFF
RefInReflect (bit-reverse) each input byte before processingtrue
RefOutReflect the final CRC register before outputtrue
XorOutXOR mask applied to the final output0xFFFFFFFF

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

NameWidthPolyInitXorOutRefInRefOutUsed In
CRC-323204C11DB7FFFFFFFFFFFFFFFF✓✓Ethernet, ZIP, PNG
CRC-32C321EDC6F41FFFFFFFFFFFFFFFF✓✓iSCSI, SCTP
CRC-16/ARC16800500000000✓✓ARC
CRC-16/IBM-3740161021FFFF0000✗✗IBM-3740 (CCITT-FALSE)
CRC-16/MODBUS168005FFFF0000✓✓Modbus RTU
CRC-88070000✗✗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:

  1. Set Data Width — how many bits per clock your FPGA design processes (8 / 16 / 32 / 64)
  2. Module Name is auto-populated (e.g., crc32_w32)
  3. 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Copyright (c) 2026 EasyFPGA. All rights reserved.
module crc32_w32 (
    input  logic        clk,
    input  logic        resetn,       // Active-low synchronous reset
    input  logic [31:0] data_in,      // Input data word (one per clock)
    output logic [31:0] crc_out,      // Registered CRC state
    output logic [31:0] crc_final     // crc_out ^ XOR_OUT (final CRC value)
);
    logic [31:0] crc_reg;
    logic [31:0] crc_next;

    // Parallel CRC combinational logic (unrolled GF(2) matrix)
    always_comb begin
        crc_next[0] = crc_reg[1] ^ crc_reg[2] ^ ... ^ data_in[0] ^ ...;
        // one line per output bit
    end

    // CRC state register
    always_ff @(posedge clk) begin
        if (!resetn) crc_reg <= 32'hFFFFFFFF;   // Init value
        else         crc_reg <= crc_next;
    end

    assign crc_out   = crc_reg;                 // (bit-reversed if RefOut=true)
    assign crc_final = crc_out ^ 32'hFFFFFFFF;  // XorOut applied
endmodule

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

PortDirectionDescription
clkinputClock, sampled on rising edge
resetninputActive-low synchronous reset — loads Init value into crc_reg
data_ininputInput data word (Data Width bits wide)
crc_outoutputRegistered CRC state; valid one clock after each data_in
crc_finaloutputcrc_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:

TestWhat It Checks
Single wordCRC after processing one data word
4-word chainCRC after processing four consecutive words without reset

Icarus Verilog (free)

1
iverilog -g2012 -o sim crc32_w32_tb.sv crc32_w32.sv && vvp sim

Vivado xsim

1
2
3
xvlog --sv crc32_w32.sv crc32_w32_tb.sv
xelab -debug typical crc32_w32_tb
xsim crc32_w32_tb --runall

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.