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
- One full data word is folded into the CRC every enabled clock cycle.
- Not reflected: for reflected protocols (Ethernet CRC-32, SD/MMC), bit-reverse each input byte and bit-reverse + invert the final CRC.
- For CRC-32 the final value is usually XORed with 0xFFFFFFFF before transmission; do that outside this module.
// 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
-- 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;
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.