Parallel CRC Generator

Generate a synthesizable parallel (one word per clock) CRC module in Verilog and VHDL from any polynomial. Presets for CRC-8, CRC-16-CCITT, CRC-16-IBM and CRC-32. Pure XOR logic, no lookup tables.

Results

Polynomial
0x04C11DB7 (top bit implicit)
CRC width / data width
32 / 8 bits
Init value
0xFFFFFFFF
2-input XOR count (approx.)
220

Notes

Verilog
// Parallel CRC: poly=0x04C11DB7 (+ implicit top bit), width=32, data=8 bits/clk
// Data shifted in MSB first, not reflected. Generated by libfpga.com/tools/crc-generator
module crc32_d8 (
    input  wire                clk,
    input  wire                rst,      // sync reset, loads INIT
    input  wire                en,       // process data_in this cycle
    input  wire [7:0]       data_in,
    output reg  [31:0]      crc_out
);
    localparam [31:0] INIT = 32'hFFFFFFFF;

    wire [31:0] c = crc_out;
    wire [31:0] crc_next;

    assign crc_next[0] = c[30] ^ c[24] ^ data_in[6] ^ data_in[0];
    assign crc_next[1] = c[31] ^ c[30] ^ c[25] ^ c[24] ^ data_in[7] ^ data_in[6] ^ data_in[1] ^ data_in[0];
    assign crc_next[2] = c[31] ^ c[30] ^ c[26] ^ c[25] ^ c[24] ^ data_in[7] ^ data_in[6] ^ data_in[2] ^ data_in[1] ^ data_in[0];
    assign crc_next[3] = c[31] ^ c[27] ^ c[26] ^ c[25] ^ data_in[7] ^ data_in[3] ^ data_in[2] ^ data_in[1];
    assign crc_next[4] = c[30] ^ c[28] ^ c[27] ^ c[26] ^ c[24] ^ data_in[6] ^ data_in[4] ^ data_in[3] ^ data_in[2] ^ data_in[0];
    assign crc_next[5] = c[31] ^ c[30] ^ c[29] ^ c[28] ^ c[27] ^ c[25] ^ c[24] ^ data_in[7] ^ data_in[6] ^ data_in[5] ^ data_in[4] ^ data_in[3] ^ data_in[1] ^ data_in[0];
    assign crc_next[6] = c[31] ^ c[30] ^ c[29] ^ c[28] ^ c[26] ^ c[25] ^ data_in[7] ^ data_in[6] ^ data_in[5] ^ data_in[4] ^ data_in[2] ^ data_in[1];
    assign crc_next[7] = c[31] ^ c[29] ^ c[27] ^ c[26] ^ c[24] ^ data_in[7] ^ data_in[5] ^ data_in[3] ^ data_in[2] ^ data_in[0];
    assign crc_next[8] = c[28] ^ c[27] ^ c[25] ^ c[24] ^ c[0] ^ data_in[4] ^ data_in[3] ^ data_in[1] ^ data_in[0];
    assign crc_next[9] = c[29] ^ c[28] ^ c[26] ^ c[25] ^ c[1] ^ data_in[5] ^ data_in[4] ^ data_in[2] ^ data_in[1];
    assign crc_next[10] = c[29] ^ c[27] ^ c[26] ^ c[24] ^ c[2] ^ data_in[5] ^ data_in[3] ^ data_in[2] ^ data_in[0];
    assign crc_next[11] = c[28] ^ c[27] ^ c[25] ^ c[24] ^ c[3] ^ data_in[4] ^ data_in[3] ^ data_in[1] ^ data_in[0];
    assign crc_next[12] = c[30] ^ c[29] ^ c[28] ^ c[26] ^ c[25] ^ c[24] ^ c[4] ^ data_in[6] ^ data_in[5] ^ data_in[4] ^ data_in[2] ^ data_in[1] ^ data_in[0];
    assign crc_next[13] = c[31] ^ c[30] ^ c[29] ^ c[27] ^ c[26] ^ c[25] ^ c[5] ^ data_in[7] ^ data_in[6] ^ data_in[5] ^ data_in[3] ^ data_in[2] ^ data_in[1];
    assign crc_next[14] = c[31] ^ c[30] ^ c[28] ^ c[27] ^ c[26] ^ c[6] ^ data_in[7] ^ data_in[6] ^ data_in[4] ^ data_in[3] ^ data_in[2];
    assign crc_next[15] = c[31] ^ c[29] ^ c[28] ^ c[27] ^ c[7] ^ data_in[7] ^ data_in[5] ^ data_in[4] ^ data_in[3];
    assign crc_next[16] = c[29] ^ c[28] ^ c[24] ^ c[8] ^ data_in[5] ^ data_in[4] ^ data_in[0];
    assign crc_next[17] = c[30] ^ c[29] ^ c[25] ^ c[9] ^ data_in[6] ^ data_in[5] ^ data_in[1];
    assign crc_next[18] = c[31] ^ c[30] ^ c[26] ^ c[10] ^ data_in[7] ^ data_in[6] ^ data_in[2];
    assign crc_next[19] = c[31] ^ c[27] ^ c[11] ^ data_in[7] ^ data_in[3];
    assign crc_next[20] = c[28] ^ c[12] ^ data_in[4];
    assign crc_next[21] = c[29] ^ c[13] ^ data_in[5];
    assign crc_next[22] = c[24] ^ c[14] ^ data_in[0];
    assign crc_next[23] = c[30] ^ c[25] ^ c[24] ^ c[15] ^ data_in[6] ^ data_in[1] ^ data_in[0];
    assign crc_next[24] = c[31] ^ c[26] ^ c[25] ^ c[16] ^ data_in[7] ^ data_in[2] ^ data_in[1];
    assign crc_next[25] = c[27] ^ c[26] ^ c[17] ^ data_in[3] ^ data_in[2];
    assign crc_next[26] = c[30] ^ c[28] ^ c[27] ^ c[24] ^ c[18] ^ data_in[6] ^ data_in[4] ^ data_in[3] ^ data_in[0];
    assign crc_next[27] = c[31] ^ c[29] ^ c[28] ^ c[25] ^ c[19] ^ data_in[7] ^ data_in[5] ^ data_in[4] ^ data_in[1];
    assign crc_next[28] = c[30] ^ c[29] ^ c[26] ^ c[20] ^ data_in[6] ^ data_in[5] ^ data_in[2];
    assign crc_next[29] = c[31] ^ c[30] ^ c[27] ^ c[21] ^ data_in[7] ^ data_in[6] ^ data_in[3];
    assign crc_next[30] = c[31] ^ c[28] ^ c[22] ^ data_in[7] ^ data_in[4];
    assign crc_next[31] = c[29] ^ c[23] ^ data_in[5];

    always @(posedge clk) begin
        if (rst)      crc_out <= INIT;
        else if (en)  crc_out <= crc_next;
    end
endmodule
VHDL
-- Parallel CRC: poly=0x04C11DB7 (+ implicit top bit), width=32, data=8 bits/clk
-- Data shifted in MSB first, not reflected. Generated by libfpga.com/tools/crc-generator
library ieee;
use ieee.std_logic_1164.all;

entity crc32_d8 is
    port (
        clk     : in  std_logic;
        rst     : in  std_logic;  -- sync reset, loads INIT
        en      : in  std_logic;
        data_in : in  std_logic_vector(7 downto 0);
        crc_out : out std_logic_vector(31 downto 0)
    );
end entity;

architecture rtl of crc32_d8 is
    constant INIT : std_logic_vector(31 downto 0) := "11111111111111111111111111111111";
    signal c : std_logic_vector(31 downto 0) := INIT;
begin
    crc_out <= c;

    process (clk)
        variable n : std_logic_vector(31 downto 0);
    begin
        if rising_edge(clk) then
            if rst = '1' then
                c <= INIT;
            elsif en = '1' then
                n(0) := c(30) xor c(24) xor data_in(6) xor data_in(0);
                n(1) := c(31) xor c(30) xor c(25) xor c(24) xor data_in(7) xor data_in(6) xor data_in(1) xor data_in(0);
                n(2) := c(31) xor c(30) xor c(26) xor c(25) xor c(24) xor data_in(7) xor data_in(6) xor data_in(2) xor data_in(1) xor data_in(0);
                n(3) := c(31) xor c(27) xor c(26) xor c(25) xor data_in(7) xor data_in(3) xor data_in(2) xor data_in(1);
                n(4) := c(30) xor c(28) xor c(27) xor c(26) xor c(24) xor data_in(6) xor data_in(4) xor data_in(3) xor data_in(2) xor data_in(0);
                n(5) := c(31) xor c(30) xor c(29) xor c(28) xor c(27) xor c(25) xor c(24) xor data_in(7) xor data_in(6) xor data_in(5) xor data_in(4) xor data_in(3) xor data_in(1) xor data_in(0);
                n(6) := c(31) xor c(30) xor c(29) xor c(28) xor c(26) xor c(25) xor data_in(7) xor data_in(6) xor data_in(5) xor data_in(4) xor data_in(2) xor data_in(1);
                n(7) := c(31) xor c(29) xor c(27) xor c(26) xor c(24) xor data_in(7) xor data_in(5) xor data_in(3) xor data_in(2) xor data_in(0);
                n(8) := c(28) xor c(27) xor c(25) xor c(24) xor c(0) xor data_in(4) xor data_in(3) xor data_in(1) xor data_in(0);
                n(9) := c(29) xor c(28) xor c(26) xor c(25) xor c(1) xor data_in(5) xor data_in(4) xor data_in(2) xor data_in(1);
                n(10) := c(29) xor c(27) xor c(26) xor c(24) xor c(2) xor data_in(5) xor data_in(3) xor data_in(2) xor data_in(0);
                n(11) := c(28) xor c(27) xor c(25) xor c(24) xor c(3) xor data_in(4) xor data_in(3) xor data_in(1) xor data_in(0);
                n(12) := c(30) xor c(29) xor c(28) xor c(26) xor c(25) xor c(24) xor c(4) xor data_in(6) xor data_in(5) xor data_in(4) xor data_in(2) xor data_in(1) xor data_in(0);
                n(13) := c(31) xor c(30) xor c(29) xor c(27) xor c(26) xor c(25) xor c(5) xor data_in(7) xor data_in(6) xor data_in(5) xor data_in(3) xor data_in(2) xor data_in(1);
                n(14) := c(31) xor c(30) xor c(28) xor c(27) xor c(26) xor c(6) xor data_in(7) xor data_in(6) xor data_in(4) xor data_in(3) xor data_in(2);
                n(15) := c(31) xor c(29) xor c(28) xor c(27) xor c(7) xor data_in(7) xor data_in(5) xor data_in(4) xor data_in(3);
                n(16) := c(29) xor c(28) xor c(24) xor c(8) xor data_in(5) xor data_in(4) xor data_in(0);
                n(17) := c(30) xor c(29) xor c(25) xor c(9) xor data_in(6) xor data_in(5) xor data_in(1);
                n(18) := c(31) xor c(30) xor c(26) xor c(10) xor data_in(7) xor data_in(6) xor data_in(2);
                n(19) := c(31) xor c(27) xor c(11) xor data_in(7) xor data_in(3);
                n(20) := c(28) xor c(12) xor data_in(4);
                n(21) := c(29) xor c(13) xor data_in(5);
                n(22) := c(24) xor c(14) xor data_in(0);
                n(23) := c(30) xor c(25) xor c(24) xor c(15) xor data_in(6) xor data_in(1) xor data_in(0);
                n(24) := c(31) xor c(26) xor c(25) xor c(16) xor data_in(7) xor data_in(2) xor data_in(1);
                n(25) := c(27) xor c(26) xor c(17) xor data_in(3) xor data_in(2);
                n(26) := c(30) xor c(28) xor c(27) xor c(24) xor c(18) xor data_in(6) xor data_in(4) xor data_in(3) xor data_in(0);
                n(27) := c(31) xor c(29) xor c(28) xor c(25) xor c(19) xor data_in(7) xor data_in(5) xor data_in(4) xor data_in(1);
                n(28) := c(30) xor c(29) xor c(26) xor c(20) xor data_in(6) xor data_in(5) xor data_in(2);
                n(29) := c(31) xor c(30) xor c(27) xor c(21) xor data_in(7) xor data_in(6) xor data_in(3);
                n(30) := c(31) xor c(28) xor c(22) xor data_in(7) xor data_in(4);
                n(31) := c(29) xor c(23) xor data_in(5);
                c <= n;
            end if;
        end if;
    end process;
end architecture;

This exact result is bookmarkable — the URL contains all your inputs. Need it in a script? Append &format=json (API docs).

About this tool

A serial CRC processes one bit per clock; at a gigabit line rate that would need a gigahertz clock. The standard trick is to unroll: advance the shift register a whole word per cycle by computing, symbolically, what each CRC bit would be after N serial steps. Each next-state bit collapses to an XOR of current CRC bits and data bits, which synthesizes to a few levels of LUTs. This generator does that unrolling for any polynomial and data width and emits the resulting equations as a Verilog or VHDL module — the same approach as the classic easics generator, verified in our test suite against a bit-serial reference. Watch the reflection convention: Ethernet and SD/MMC shift bits in LSB-first, so reverse input bytes and the final CRC as noted on the page.

Related tools