Verilog implementation of CRC (cyclic redundancy check)

Algorithm introduction:

A channel coding technology used to detect errors that may occur after data transmission or storage. It uses modulo 2 division for verification. It has fast calculation speed and strong error detection capabilities. It has different standard parameter models. The higher the standard, the higher the error detection. The better the capability and accuracy.

Algorithm implementation:

(Take CRC-5 as an example (initial value 00)): Its generating polynomial is X5 + X3 + 1. The input and output do not need to be flipped. Let the data string be 100101

  1. According to the coefficients of different powers of the generating polynomial, the binary number is: 101001 (divisor). Since the first and last bits must be 1, the first bit is omitted and is 01001 = 0x099 ( POLY)
  2. Add 0 to the data string with the number of coefficient digits after omitting the first digit, and obtain a new data string of 100101 00000 (dividend).
  3. Perform modulo 2 division on the new data string and the divisor to obtain a 5-digit remainder, which is the CRC check code 10111.
  4. Splice the obtained remainder at the end of the data string to obtain a new data string,
  5. Divide the data string modulo 2 by the divisor. If there is no remainder, it means there is no error.

Implement the circuit:

Draw standard circuits based on polynomials

List expressions:

D0 <= data_in ^ D4;

D1 <= D0 ;

D2 <= D1;

D3 <= data_in ^ D4 ^D2;

D4 <= D3;

Data-in

D0

D1

D2

D3

D4

0

0

0

0

0

0

1

1

0

0

1

0

0

0

1

0

0

1

0

1

0

1

1

0

1

1

1

0

0

1

0

1

1

1

1

0

1

1

1

1

0

1

When 6 clock cycles are over, the value of D4-D0 is the CRC check code 10111

verilogImplementation: (.V file)

module crc (
input [5:0] data_in , //Input the data to be detected
output [4:0] crc_data , //CRC check code output
input rst,
inputclk,
output wire [4:0] result , // The remainder used for testing at the end
output wire [10:0] string_data // Define the output CRC data string
) ;
\t\t\t
\t\t\t
reg [4:0] reminder_1, reminder_2, //Two sets of intermediate variables, used to store the values of the current state and next state of the circuit
mod1, mod2;

\t\t\t\t
wire [5:0] data;
integer i =0;
integer j = 0;


assign string_data = {crc_data[0],crc_data[1],crc_data[2],crc_data[3],crc_data[4],data_in[0],data_in[1],data_in[2],data_in[3],data_in [4],data_in[5]}; //Splice the input data and CRC check code
assign data = {data_in[0],data_in[1],data_in[2],data_in[3],data_in[4],data_in[5]}; //Storage input data 100101
assign crc_data= {reminder_2[4],reminder_2[3],reminder_2[2],reminder_2[1],reminder_2[0]}; //Pass the intermediate variable data into the CRC value
assign result = {mod2[4],mod2[3],mod2[2],mod2[1],mod2[0]}; //remainder

always @ (*) begin

reminder_1[0] <= data [i] ^ reminder_2 [4] ; //Write the relationship based on the circuit diagram
reminder_1[1] <= reminder_2 [0] ; //D0 <= data_in ^ D4
reminder_1[2] <= reminder_2 [1] ; //D1 <= D0
reminder_1[3] <= data [i] ^ reminder_2 [4] ^ reminder_2 [2] ; //D2 <= D1
reminder_1[4] <= reminder_2 [3] ; //D3 <= data_in ^ D4 ^D2
//D4 <= D3
mod1[0] <= string_data [j] ^ mod2 [4] ;
mod1[1] <= mod2 [0] ;
mod1[2] <= mod2 [1] ;
mod1[3] <= string_data [j] ^ mod2 [4] ^ mod2 [2] ;
mod1[4] <= mod2 [3] ;



end

always @ (posedge clk or posedge rst ) begin
if(rst) begin
reminder_2 <= {5{1'b0}}; //Reset to clear circuit status to 0
mod2 <= {5{1'b0}};
end
else if (i <= 5 & amp; & amp; j<=10)begin
mod2 <= mod1 ;
reminder_2 <= reminder_1; // i increments, controlling the order of data_in entering (LSB)
i = i + 1; // j increments, controlling the order of string_data entering (LSB)
j = j + 1;
end
else if (i > 5 & amp; & amp; j>10)begin
mod2 <= mod2 ;
reminder_2 <=reminder_2;
end
else begin
reminder_2 <=reminder_2;
mod2 <= mod1 ;
j = j + 1;
end
\t\t\t
end

endmodule

(test file)

`timescale 1 ps/ 1 ps
module crc_vlg_tst();

reg clk;
reg [5:0] data_in;
reg rst;
                                               
wire [4:0] crc_data;
wire [4:0] result ;
wire [10:0] string_data;



                        
crc i1 (

.clk(clk),
.crc_data(crc_data),
.data_in(data_in),
.rst(rst) ,
.string_data(string_data) ,
.result(result)
\t
);
always #10 clk = ~clk ;
initial
begin
clk = 0;
rst = 1;
data_in <= 6'b100101;
#20
rst = 0;
                                              

                                         
$display("Running testbench");
end
                                                
endmodule

Waveform validation:

It can be seen that the data string after splicing the CRC check code passes through the circuit, and the final remainder is 00000, which proves that the data is correct, and the CRC check code is obtained through online calculation.

I just started researching, and the code is relatively complicated. If there are any mistakes, experts are welcome to communicate and correct me!