_TOP_MENU

Feb 23, 2025

Cyclic Redundancy Check (CRC) Generator - RTL Code



A Cyclic Redundancy Check (CRC) is a popular error-detection technique used in communication protocols and file storage systems to check for data integrity. It involves the use of a polynomial division method to generate a checksum value (CRC code) based on the input data, which can later be used to detect any alterations in the transmitted data.

To implement a CRC generator in RTL (Register-Transfer Level), we need to design a hardware module that computes the CRC value for a given input. Below is an example of how you can write Verilog RTL code for a CRC-16-CCITT-FALSE generator. This CRC uses a 16-bit polynomial, 0x11021, commonly used in communications.

Verilog Code for CRC-16-CCITT-FALSE Generator:

module crc16_ccitt_false(
    input clk,                    // Clock signal
    input reset,                  // Reset signal
    input [7:0] data_in,          // 8-bit input data
    input data_valid,             // Data valid signal to indicate when data_in is valid
    output reg [15:0] crc_out     // 16-bit CRC output
);

    // Polynomial: 0x11021 (x^16 + x^12 + x^5 + 1)
    reg [15:0] crc_reg;            // Internal CRC register

    // CRC shift register calculation
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            // Reset the CRC register to initial value 16'hFFFF
            crc_reg <= 16'hFFFF;
        end
        else if (data_valid) begin
            // Perform CRC calculation for each byte of data
            crc_reg <= crc_reg ^ {8'b0, data_in};  // XOR input data with CRC register
            // Perform polynomial division (shift and XOR with polynomial if MSB is 1)
            for (int i = 0; i < 8; i = i + 1) begin
                if (crc_reg[15] == 1) begin
                    crc_reg = {crc_reg[14:0], 1'b0} ^ 16'h11021;
                end else begin
                    crc_reg = {crc_reg[14:0], 1'b0};
                end
            end
        end
    end

    // Assign the calculated CRC value to the output
    always @(posedge clk or posedge reset) begin
        if (reset)
            crc_out <= 16'hFFFF;  // Reset CRC to 0xFFFF
        else if (data_valid)
            crc_out <= crc_reg;   // Update CRC output when data is valid
    end

endmodule

Explanation of the Code:

  1. Input/Output Ports:

    • clk: Clock input that synchronizes the module.
    • reset: Asynchronous reset signal that initializes the CRC value to 0xFFFF.
    • data_in: 8-bit input data that will be processed in the CRC calculation.
    • data_valid: A signal that indicates when valid data is present on data_in.
    • crc_out: The 16-bit CRC output, which is the result of the CRC calculation.
  2. Internal CRC Register (crc_reg):

    • The internal CRC register holds the intermediate and final CRC value, which is updated as data is processed.
  3. CRC Calculation (Core Logic):

    • The CRC generator uses a polynomial, specifically 0x11021 (x^16 + x^12 + x^5 + 1), to perform the error-checking.
    • On every valid data input (data_valid), the CRC register is XORed with the incoming data byte (data_in).
    • Then, a bit-shifting loop (for loop) is applied where the bits are shifted, and if the most significant bit (MSB) is 1, the polynomial 0x11021 is XORed with the CRC register. This simulates polynomial division.
  4. Reset and Output Assignment:

    • On a reset, the CRC register is initialized to 0xFFFF.
    • After each valid data cycle, the CRC output is updated with the value in the CRC register.

Key Points:

  • Polynomial: The polynomial used here is 0x11021, which is common in CRC-16-CCITT-FALSE. You may modify this polynomial to suit your specific CRC standard (e.g., CRC-16-ANSI, CRC-32, etc.).
  • Data Processing: Data is processed in 8-bit chunks, typical for many data transmission systems.
  • CRC Register Size: In this example, a 16-bit CRC register (crc_reg) is used. Adjust the register size based on the CRC width for your application (e.g., 32 bits for CRC-32).
  • Reset Behavior: The reset signal initializes the CRC to 0xFFFF, which is a common practice for CRC-16-CCITT-FALSE.

Simulation and Testing:

To verify the functionality of this module, you can write a simple testbench to simulate the CRC generator with some input data:

module tb_crc16_ccitt_false;

    reg clk;
    reg reset;
    reg [7:0] data_in;
    reg data_valid;
    wire [15:0] crc_out;

    // Instantiate the CRC16-CCITT-FALSE module
    crc16_ccitt_false crc_gen (
        .clk(clk),
        .reset(reset),
        .data_in(data_in),
        .data_valid(data_valid),
        .crc_out(crc_out)
    );

    // Clock generation
    always begin
        clk = 1'b0;
        #5 clk = 1'b1;
        #5;
    end

    // Test stimulus
    initial begin
        // Initialize signals
        reset = 1;
        data_in = 8'h00;
        data_valid = 0;
        #10;

        reset = 0;
        data_in = 8'hA5;  // Example input data
        data_valid = 1;
        #10;

        data_in = 8'h5A;  // Next byte of data
        #10;

        data_valid = 0;
        #10;

        // End of simulation
        $stop;
    end

endmodule

Conclusion:

This Verilog RTL code implements a basic CRC-16-CCITT-FALSE generator. It takes in 8-bit data chunks and computes the 16-bit CRC checksum using a standard polynomial division algorithm. The code can be adapted to different CRC standards (e.g., CRC-32) by modifying the polynomial and register size as necessary.

No comments:

Post a Comment