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.

Cores that use this

Open FPGA IP from the registry you can drop in instead of building from scratch.

Related tools