m FPGA-based CRC cyclic redundancy check system verilog implementation, including testbench

Table of contents

1. Algorithm simulation effect

2. Algorithms involve an overview of theoretical knowledge

3. Verilog core program

4. Complete algorithm code file


1. Algorithm simulation effect

The system has been developed on two platforms, namely:

Vivado2019.2

Quartusii18.0+ModelSim-Altera 6.6d Starter Edition

The Vivado2019.2 simulation results are as follows:

The test results of Quartusii18.0+ModelSim-Altera 6.6d Starter Edition are as follows:

 Compare the matlab results:

2. Algorithms involve an overview of theoretical knowledge

       CRC (Cyclic Redundancy Check) is a data verification technology widely used in communication and storage systems. It generates a redundant check code by performing polynomial division on the data, and appends it to the data and sends it to the receiver. After receiving the data, the receiver performs polynomial division again. If the calculated check code is the same as the received If the received check codes are the same, it indicates that there is no error in the data.

       The basic principle of the CRC check is to generate a redundant check code by performing polynomial division on the data. Specifically, assume that a CRC check is to be performed on an N-bit data to generate an M-bit check code, where M is usually smaller than N, and generally takes 16 or 32 bits. The generator polynomial is generally expressed as G(x), which is a binary number with M+1 bits, and the highest bit and the lowest bit are both 1. The selection of the generator polynomial is critical to the performance of the CRC check.


Specifically, the CRC check process is as follows:
        shift the N-bit data D(x) to the left by M bits, that is, fill the highest bit with M 0s, and obtain an N+M-bit number D'(x). Dividing D'(x) by G(x) yields the quotient Q(x) and remainder R(x). Wherein, Q(x) is an N-bit binary number, and R(x) is an M-bit binary number, that is, a check code. Append R(x) to the end of the original data D(x) to get a number T(x) of N+M digits, that is, T(x) = D(x) * 2^M + R(x). Send T(x) to the receiver. The receiver performs the same polynomial division operation as the sender on the received data T'(x) to obtain the remainder R'(x). If R'(x) is equal to 0, it indicates that there is no error in the data; otherwise, an error has occurred in the data. The above is the basic principle of CRC check. Below we will introduce how to implement CRC check in FPGA.

The general steps for FPGA to realize CRC check are as follows:
      Select the appropriate generator polynomial G(x). The selection of the generator polynomial is critical to the performance of the CRC check. Generally speaking, the more digits of the generator polynomial, the better the performance of the CRC check, but at the same time it will increase the complexity of calculation and the consumption of hardware resources. In practical applications, it is necessary to select an appropriate generator polynomial according to the specific situation.
      Implements polynomial division. Polynomial division is the core algorithm of CRC check, which needs to be implemented in FPGA. Specifically, the polynomial division can be implemented in two ways: hardware implementation or software implementation. The hardware implementation can be realized by a combinational logic circuit, and the software implementation can be realized by a microprocessor inside the FPGA or an external processor.
       Implement data shift and data append. Data shifting can be realized through the shift register inside the FPGA, and data addition can be realized through combinational logic circuits.
     Receiver's checksum operation. The receiver needs to perform the same polynomial division operation as the sender on the received data to obtain the remainder R'(x). If R'(x) is equal to 0, it indicates that there is no error in the data; otherwise, an error has occurred in the data.
Below we will introduce in detail how to implement CRC check in FPGA.
Selecting the Generator Polynomial
       Selecting the generator polynomial is the first step in the CRC check. When selecting a generator polynomial, the following factors need to be considered:
(1) The number of polynomial bits: the more polynomial bits, the better the CRC check performance, but it will also increase the computational complexity and hardware resource consumption.
(2) Both the highest bit and the lowest bit of the generator polynomial are 1.
(3) The coefficients of the generator polynomial should be distributed as much as possible to ensure the performance of the CRC check.
The following table lists some commonly used generating polynomials:
polynomial digits CRC check code length
x^16 + x^15 + x^2 + 1 
In practical applications, it is necessary to select an appropriate generator polynomial according to the specific situation.
Realize polynomial division
       Polynomial division is the core algorithm of CRC check, it needs to realize in FPGA. Polynomial division can be implemented in hardware or software in two ways.
      Hardware implementation can be realized by combinational logic circuits. In hardware implementation, polynomial division has the advantage of parallel processing, which can greatly increase the calculation speed. Specifically, polynomial division can be expressed as the following circuit diagram:

3. Verilog core program

`timescale 1ns / 1ps
.......................................................................
//x^16+x^15+x^2+1
//1- 1 0 0 0 -0 0 0 0 -0 0 0 0- 0 1 0 1 
assign tmp2[0] = xtmp0[8] ^ xtmp0[9] ^ xtmp0[10] ^ xtmp0[11] ^ xtmp0[12] ^ xtmp0[13] ^ xtmp0[14] ^ xtmp0[15] ^ i_x[0] ^ i_x[1] ^ i_x[2] ^ i_x[3] ^ i_x[4] ^ i_x[5] ^ i_x[6] ^ i_x[7];
assign tmp2[1] = xtmp0[9] ^ xtmp0[10] ^ xtmp0[11] ^ xtmp0[12] ^ xtmp0[13] ^ xtmp0[14] ^ xtmp0[15] ^ i_x[1] ^ i_x[2] ^ i_x[3] ^ i_x[4] ^ i_x[5] ^ i_x[6] ^ i_x[7];
assign tmp2[2] = xtmp0[8] ^ xtmp0[9] ^ i_x[0] ^ i_x[1];
assign tmp2[3] = xtmp0[9] ^ xtmp0[10] ^ i_x[1] ^ i_x[2];
assign tmp2[4] = xtmp0[10] ^ xtmp0[11] ^ i_x[2] ^ i_x[3];
assign tmp2[5] = xtmp0[11] ^ xtmp0[12] ^ i_x[3] ^ i_x[4];
assign tmp2[6] = xtmp0[12] ^ xtmp0[13] ^ i_x[4] ^ i_x[5];
assign tmp2[7] = xtmp0[13] ^ xtmp0[14] ^ i_x[5] ^ i_x[6];
assign tmp2[8] = xtmp0[0] ^ xtmp0[14] ^ xtmp0[15] ^ i_x[6] ^ i_x[7];
assign tmp2[9] = xtmp0[1] ^ xtmp0[15] ^ i_x[7];
assign tmp2[10] = xtmp0[2];
assign tmp2[11] = xtmp0[3];
assign tmp2[12] = xtmp0[4];
assign tmp2[13] = xtmp0[5];
assign tmp2[14] = xtmp0[6];
......................................................................
endmodule
00_012m

4. Complete algorithm code file

V

Guess you like

Origin blog.csdn.net/hlayumi1234567/article/details/130651347