Analysis of CRC Generator (Generator of synthesizable CRC functions)

1. 1bit serial CRC using Synthesized CRC functions
 
 Polynomial:1 + x2 + x5

 Data bus width: 1
 
  Let's see generated code by condition above.

///////////////////////////////////////////////////////////////////////
// File:  CRC5_D1.v                             
// Date:  Wed May  4 22:47:04 2005                                                      
//                                                                     
// Copyright (C) 1999-2003 Easics NV.                 
// This source file may be used and distributed without restriction    
// provided that this copyright statement is not removed from the file 
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
//   * polynomial: (0 2 5)
//   * data width: 1
//                                                                     
// Info: tools@easics.be
//       http://www.easics.com                                  
///////////////////////////////////////////////////////////////////////


module CRC5_D1;

  // polynomial: (0 2 5)
  // data width: 1
  function [4:0] nextCRC5_D1;

    input Data;
    input [4:0] CRC;

    reg [0:0] D;
    reg [4:0] C;
    reg [4:0] NewCRC;

  begin

    D[0] = Data;
    C = CRC;

    NewCRC[0] = D[0] ^ C[4];
    NewCRC[1] = C[0];
    NewCRC[2] = D[0] ^ C[1] ^ C[4];
    NewCRC[3] = C[2];
    NewCRC[4] = C[3];

    nextCRC5_D1 = NewCRC;

  end

  endfunction

endmodule

Here is a general imprementation of CRC using shift register.

Since polynomial is 1 + x2 + x5 ,

g4=0;
g3=0;
g2=1;
g1=0;
g0=1;

You see the generated code is the same as general implementation of CRC.
Here is a complete module.

///////////////////////////////////////////////////////////////////////
// File:  CRC5_D1.v                             
// Date:  Tue May  3 05:20:40 2005                                                      
//                                                                     
// Copyright (C) 1999-2003 Easics NV.                 
// This source file may be used and distributed without restriction    
// provided that this copyright statement is not removed from the file 
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
//   * polynomial: (0 2 5)
//   * data width: 1
//                                                                     
// Info: tools@easics.be
//       http://www.easics.com                                  
///////////////////////////////////////////////////////////////////////

//Add some interface  May.4.2005 Tak.Sugawara

module  CRC5_D1_Module #(parameter integer initial_value=-1, poly_width=5) (input clock,
                                             input data,sync_reset,hold,
                                             output reg [poly_width-1:0] crc);

        always @(posedge clock) begin
          if (sync_reset) crc <=initial_value;
                else if (hold) crc <=crc;
                else crc<=nextCRC5_D1(data,crc);
        end

  // polynomial: (0 2 5)
  // data width: 1

  function [4:0] nextCRC5_D1;

    input Data;
    input [4:0] CRC;

    reg [0:0] D;
    reg [4:0] C;
    reg [4:0] NewCRC;

  begin

    D[0] = Data;
    C = CRC;

    NewCRC[0] = D[0] ^ C[4];
    NewCRC[1] = C[0];
    NewCRC[2] = D[0] ^ C[1] ^ C[4];
    NewCRC[3] = C[2];
    NewCRC[4] = C[3];

    nextCRC5_D1 = NewCRC;

  end

  endfunction

endmodule

,and test bench.

module CRC5D1_test_bench;
                parameter integer initial_value=-1;
                parameter integer poly_width=5;
                parameter integer maximum_no_of_errors=3;
                parameter integer data_length=10;
                reg data;
                reg clock=0;
                reg sync_reset=1;
                reg hold=0, receiver_hold=0;
                wire [poly_width-1:0] crc_sender,crc_receiver;
                reg done=0;
                reg error=0;
                integer i,test_loops,error_counter;
                wire receive_data=data^ error;
        

        always #10 clock=~clock;

        initial begin
                        #5;
                        test_loops=0;
//Test 1 Make sure no crc error occurs
                        repeat (100) begin
                                test_loops=test_loops+1;
                                if (test_loops%100==0) $display("Test Loops=%d",test_loops);
                                
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        @(negedge clock);
                                end
                                hold=1;
                                for (i=0;i<poly_width;i=i+1) begin
                                  data=crc_sender[poly_width-1-i];
                                        @(negedge clock);
                                end
                                done=1;
                                if (crc_receiver !==0) $display("Miss Detectio or Programming Error");
                                @(negedge clock);
                                done=0;
                        end
//Make sure crc error occurs
                        test_loops=0;
                        repeat (100) begin
                                test_loops=test_loops+1;
                                if (test_loops%1000==0) $display("Test Loops=%d",test_loops);
                        
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;error_counter=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        if (i==0) begin
                                                error=1;//We add at least one error. 
                                                error_counter=error_counter+1;
                                        end else begin//Limit maxinum no of errors
                                                if (error_counter <maximum_no_of_errors) begin
                                                        error=$random;//$random error addition
                                                        error_counter=error_counter+1;
                                                end
                                        end
                                        @(negedge clock);
                                end
                                hold=1;//Stop CRC generation in sender
                                for (i=0;i<poly_width;i=i+1) begin
                                        data=crc_sender[poly_width-1-i];//CRC polynominal are sent
                                        @(negedge clock);
                                end
                                done=1;
                                if (crc_receiver ==0) $display("Miss Error Detection or Programming Error Test Loops=%d",test_loops);
                                @(negedge clock);
                                done=0;
                        end



                        $finish;
        end


CRC5_D1_Module #(.initial_value(initial_value),.poly_width(poly_width)) crc_sender( clock,
                                                    data,sync_reset,hold,
                                                           crc_sender);

CRC5_D1_Module #(.initial_value(initial_value),.poly_width(poly_width)) crc_receiver( clock,
                                                    receive_data,sync_reset,receiver_hold,
                                                   crc_receiver);

endmodule

2. 5bit serial CRC using Synthesized CRC functions
 
 Polynomial:1 + x2 + x5

 Data bus width: 5
 
  Let's see generated code by condition above

///////////////////////////////////////////////////////////////////////
// File:  CRC5_D5.v                             
// Date:  Tue May  3 09:53:42 2005                                                      
//                                                                     
// Copyright (C) 1999-2003 Easics NV.                 
// This source file may be used and distributed without restriction    
// provided that this copyright statement is not removed from the file 
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
//   * polynomial: (0 2 5)
//   * data width: 5
//                                                                     
// Info: tools@easics.be
//       http://www.easics.com                                  
///////////////////////////////////////////////////////////////////////


module CRC5_D5;

  // polynomial: (0 2 5)
  // data width: 5
  // convention: the first serial data bit is D[4]
  function [4:0] nextCRC5_D5;

    input [4:0] Data;
    input [4:0] CRC;

    reg [4:0] D;
    reg [4:0] C;
    reg [4:0] NewCRC;

  begin

    D = Data;
    C = CRC;

    NewCRC[0] = D[3] ^ D[0] ^ C[0] ^ C[3];
    NewCRC[1] = D[4] ^ D[1] ^ C[1] ^ C[4];
    NewCRC[2] = D[3] ^ D[2] ^ D[0] ^ C[0] ^ C[2] ^ C[3];
    NewCRC[3] = D[4] ^ D[3] ^ D[1] ^ C[1] ^ C[3] ^ C[4];
    NewCRC[4] = D[4] ^ D[2] ^ C[2] ^ C[4];

    nextCRC5_D5 = NewCRC;

  end

  endfunction

endmodule

Where the code come from? That is next problem.
We can define transition matrix ,the same function as 1bit serial CRC as follows.


To compile 5bit parallel, just do it by mathematica.

Clear[g0,g1,g2,g3,g4,g5,g6,g7]

a4v={D4,0,D4,0,0}
a3v={D3,0,D3,0,0}
a2v={D2,0,D2,0,0}
a1v={D1,0,D1,0,0}
a0v={D0,0,D0,0,0}
CC={c0,c1,c2,c3,c4}


mat[x_] ={{0,0,0,0,g0},
          {1,0,0,0,g1},
          {0,1,0,0,g2},
          {0,0,1,0,g3},
          {0,0,0,1,g4}}
MatrixForm[mat[x_]] 
g0=1
g1=0
g2=1
g3=0
g4=0

(* Some examples *)
MatrixForm[mat[x].CC+a0v] (* 1 Degree *)
MatrixForm[mat[x].(mat[x].CC+a1v)+a0v]  (* 2 Degree *)
MatrixForm[mat[x].(mat[x].(mat[x].CC+a2v)+a1v)+a0v]  (* 3 Degree *)
MatrixForm[mat[x].(mat[x].(mat[x].(mat[x].CC+a3v)+a2v)+a1v)+a0v] (* 
  4 Degree *)

(* Solve the problem *)
MatrixForm[MatrixPower[mat[x],5].CC+
                MatrixPower[mat[x],4].a4v+
                        MatrixPower[mat[x],3].a3v+
                            MatrixPower[mat[x],2].a2v+
                                                MatrixPower[mat[x],1].a1v+a0v] (* 5 Degree *)

Then mathematica computes as follows.


You see the same code is generated by mathematica.
Here is a complete module and test bench

///////////////////////////////////////////////////////////////////////
// File:  CRC5_D5.v                             
// Date:  Tue May  3 09:53:42 2005                                                      
//                                                                     
// Copyright (C) 1999-2003 Easics NV.                 
// This source file may be used and distributed without restriction    
// provided that this copyright statement is not removed from the file 
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
//   * polynomial: (0 2 5)
//   * data width: 5
//                                                                     
// Info: tools@easics.be
//       http://www.easics.com                                  
///////////////////////////////////////////////////////////////////////

//Add interface for test May.4.2005 Tak.Sugawara

module  CRC5_D5_Module #(parameter integer initial_value=-1, poly_width=5,data_width=5) (input clock,
                                             input [data_width-1:0] data,
                                             input sync_reset,hold,
                                             output reg [poly_width-1:0] crc);

        always @(posedge clock) begin
          if (sync_reset) crc <=initial_value;
                else if (hold) crc <=crc;
                else crc<=nextCRC5_D5(data,crc);
        end

  // polynomial: (0 2 5)
  // data width: 5
  // convention: the first serial data bit is D[4]
  function [4:0] nextCRC5_D5;

    input [4:0] Data;
    input [4:0] CRC;

    reg [4:0] D;
    reg [4:0] C;
    reg [4:0] NewCRC;

  begin

    D = Data;
    C = CRC;

    NewCRC[0] = D[3] ^ D[0] ^ C[0] ^ C[3];
    NewCRC[1] = D[4] ^ D[1] ^ C[1] ^ C[4];
    NewCRC[2] = D[3] ^ D[2] ^ D[0] ^ C[0] ^ C[2] ^ C[3];
    NewCRC[3] = D[4] ^ D[3] ^ D[1] ^ C[1] ^ C[3] ^ C[4];
    NewCRC[4] = D[4] ^ D[2] ^ C[2] ^ C[4];

    nextCRC5_D5 = NewCRC;

  end

  endfunction

endmodule

module CRC5D5_test_bench;
                parameter integer initial_value=-1;
                parameter integer poly_width=5;
                parameter integer data_width=poly_width;
                parameter integer maximum_no_of_errors=3;
                parameter integer data_length=10;
        
                reg clock=0;
                reg sync_reset=1;
                reg hold=0, receiver_hold=0;
                wire [poly_width-1:0] crc_sender,crc_receiver;
                reg done=0;
                integer i,test_loops,error_counter=0;
        
                reg error=0;
                reg [data_width-1:0] data=0;
                wire  [data_width-1:0] receive_data=data^ error;
        

        always #10 clock=~clock;

        initial begin
                        #5;
                        test_loops=0;
//Test 1 Make sure no crc error occurs
                        repeat (100) begin
                                test_loops=test_loops+1;
                                if (test_loops%100==0) $display("Test Loops=%d",test_loops);
                                
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        @(negedge clock);
                                end
                                hold=1;
                                data=crc_sender;
                                @(negedge clock);
                                done=1;
                                if (crc_receiver !==0) $display("Miss Detectio or Programming Error");
                                @(negedge clock);
                                done=0;
                        end
//Make sure crc error occurs
                        test_loops=0;
                        repeat (100) begin
                                test_loops=test_loops+1;
                                if (test_loops%1000==0) $display("Test Loops=%d",test_loops);
                        
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;error_counter=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        if (i==0) begin
                                                error=1;//We add at least one error. 
                                                error_counter=error_counter+1;
                                        end else begin//Limit maxinum no of errors
                                                if (error_counter <maximum_no_of_errors) begin
                                                        error=$random;//$random error addition
                                                        error_counter=error_counter+1;
                                                end
                                        end
                                        @(negedge clock);
                                end
                                hold=1;//Stop CRC generation in sender
                                data=crc_sender;//CRC polynominal are sent
                                @(negedge clock);
                                done=1;
                                if (crc_receiver ==0) $display("Miss Error Detection or Programming Error Test Loops=%d",test_loops);
                                @(negedge clock);
                                done=0;
                        end



                        $finish;
        end


CRC5_D5_Module #(.initial_value(initial_value),.poly_width(poly_width),.data_width(data_width)) crc_sender( clock,
                                                    data,sync_reset,hold,
                                                           crc_sender);

CRC5_D5_Module #(.initial_value(initial_value),.poly_width(poly_width),.data_width(data_width)) crc_receiver( clock,
                                                    receive_data,sync_reset,receiver_hold,
                                                   crc_receiver);

endmodule

3. 8bit serial CRC using Synthesized CRC functions
 Here is an another example.

 Polynomial: 1 + x1 + x2 + x8

 Data bus width: 4/8
 
 We define transition matrix.

Here is a mathematica code.

Clear[g0,g1,g2,g3,g4,g5,g6,g7]
a7v={D7,D7,D7,0,0,0,0,0}
a6v={D6,D6,D6,0,0,0,0,0}
a5v={D5,D5,D5,0,0,0,0,0}
a4v={D4,D4,D4,0,0,0,0,0}
a3v={D3,D3,D3,0,0,0,0,0}
a2v={D2,D2,D2,0,0,0,0,0}
a1v={D1,D1,D1,0,0,0,0,0}
a0v={D0,D0,D0,0,0,0,0,0}
CC={c0,c1,c2,c3,c4,c5,c6,c7}
mat[x_] ={ {0,0,0,0,0,0,0,g0},
           {1,0,0,0,0,0,0,g1},
           {0,1,0,0,0,0,0,g2},
           {0,0,1,0,0,0,0,g3},
           {0,0,0,1,0,0,0,g4},
           {0,0,0,0,1,0,0,g5},
           {0,0,0,0,0,1,0,g6},
           {0,0,0,0,0,0,1,g7}}  

        MatrixForm[mat[x_]] 
g0=1
g1=1
g2=1
g3=0
g4=0
g5=0
g6=0
g7=0
(* Solve the problem degree 4*)
A4=MatrixPower[mat[x],4].CC+
                         MatrixPower[mat[x],3].a3v+
                          MatrixPower[mat[x],2].a2v+
                                         MatrixPower[mat[x],1].a1v+a0v   
(* Solve the problem dgree 8 *)
A8=MatrixPower[mat[x],8].CC+
MatrixPower[mat[x],7].a7v+
        MatrixPower[mat[x],6].a6v+
         MatrixPower[mat[x],5].a5v+
                 MatrixPower[mat[x],4].a4v+
                         MatrixPower[mat[x],3].a3v+
                          MatrixPower[mat[x],2].a2v+
                                         MatrixPower[mat[x],1].a1v+a0v   

MatrixForm[A4] 

MatrixForm[A8] 
MatrixForm[PolynomialMod[A8,2]]  (*  Reduce! *)

The result of computation of mathematica for 4 degree

The result of computation of mathematica for 8 degree


Note GF(2) addition is exor and 2 D7=> 0, 2 C7 =>0 ,



Here is a complete module and test bench for 4bits data width.
You see the same result as mathematica computation. Same program can be written in any language, such as c++, perl,and matlab.

///////////////////////////////////////////////////////////////////////
// File:  CRC8_D4.v                             
// Date:  Wed May  4 09:56:21 2005                                                      
//                                                                     
// Copyright (C) 1999-2003 Easics NV.                 
// This source file may be used and distributed without restriction    
// provided that this copyright statement is not removed from the file 
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
//   * polynomial: (0 1 2 8)
//   * data width: 4
//                                                                     
// Info: tools@easics.be
//       http://www.easics.com                                  
///////////////////////////////////////////////////////////////////////



//Add interface for test May.4.2005 Tak.Sugawara

module  CRC8_D4_Module #(parameter integer initial_value=-1, poly_width=8,data_width=4) (input clock,
                                             input [data_width-1:0] data,
                                             input sync_reset,hold,
                                             output reg [poly_width-1:0] crc);

        always @(posedge clock) begin
          if (sync_reset) crc <=initial_value;
                else if (hold) crc <=crc;
                else crc<=nextCRC8_D4(data,crc);
        end
  // polynomial: (0 1 2 8)
  // data width: 4
  // convention: the first serial data bit is D[3]
  function [7:0] nextCRC8_D4;

    input [3:0] Data;
    input [7:0] CRC;

    reg [3:0] D;
    reg [7:0] C;
    reg [7:0] NewCRC;

  begin

    D = Data;
    C = CRC;

    NewCRC[0] = D[0] ^ C[4];
    NewCRC[1] = D[1] ^ D[0] ^ C[4] ^ C[5];
    NewCRC[2] = D[2] ^ D[1] ^ D[0] ^ C[4] ^ C[5] ^ C[6];
    NewCRC[3] = D[3] ^ D[2] ^ D[1] ^ C[5] ^ C[6] ^ C[7];
    NewCRC[4] = D[3] ^ D[2] ^ C[0] ^ C[6] ^ C[7];
    NewCRC[5] = D[3] ^ C[1] ^ C[7];
    NewCRC[6] = C[2];
    NewCRC[7] = C[3];

    nextCRC8_D4 = NewCRC;

  end

  endfunction

endmodule
module CRC8D4_test_bench;
                parameter integer initial_value=-1;
                parameter integer poly_width=8;
                parameter integer data_width=poly_width/2;
                parameter integer maximum_no_of_errors=6;
                parameter integer data_length=10;
        
                reg clock=0;
                reg sync_reset=1;
                reg hold=0, receiver_hold=0;
                wire [poly_width-1:0] crc_sender,crc_receiver;
                reg done=0;
                integer i,test_loops,error_counter=0;
        
                reg error=0;
                reg [data_width-1:0] data=0;
                wire  [data_width-1:0] receive_data=data^ error;
        

        always #10 clock=~clock;

        initial begin
                        #5;
                        test_loops=0;
//Test 1 Make sure no crc error occurs
                        repeat (100) begin
                                test_loops=test_loops+1;
                                if (test_loops%100==0) $display("Test Loops=%d",test_loops);
                                
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        @(negedge clock);
                                end
                                hold=1;
                                for (i=0;i<2;i=i+1) begin
                                        data=crc_sender[poly_width-1-data_width*i  -:data_width];
                                        @(negedge clock);
                                end
                        
                                done=1;
                                if (crc_receiver !==0) $display("Miss Detectio or Programming Error");
                                @(negedge clock);
                                done=0;
                        end
//Make sure crc error occurs
                        test_loops=0;
                        repeat (1000) begin
                                test_loops=test_loops+1;
                                if (test_loops%1000==0) $display("Test Loops=%d",test_loops);
                        
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;error_counter=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        if (i==0) begin
                                                error=1;//We add at least one error. 
                                                error_counter=error_counter+1;
                                        end else begin//Limit maxinum no of errors
                                                if (error_counter <maximum_no_of_errors) begin
                                                        error=$random;//$random error addition
                                                        error_counter=error_counter+1;
                                                end
                                        end
                                        @(negedge clock);
                                end
                                hold=1;//Stop CRC generation in sender
                                for (i=0;i<2;i=i+1) begin
                                        data=crc_sender[poly_width-1-data_width*i  -:data_width];
                                        @(negedge clock);
                                end
                        
                                done=1;
                                if (crc_receiver ==0) $display("Miss Error Detection or Programming Error Test Loops=%d",test_loops);
                                @(negedge clock);
                                done=0;
                        end



                        $finish;
        end


CRC8_D4_Module #(.initial_value(initial_value),.poly_width(poly_width),.data_width(data_width)) crc_sender( clock,
                                                    data,sync_reset,hold,
                                                           crc_sender);

CRC8_D4_Module #(.initial_value(initial_value),.poly_width(poly_width),.data_width(data_width)) crc_receiver( clock,
                                                    receive_data,sync_reset,receiver_hold,
                                                   crc_receiver);

endmodule

Here is a complete module and test bench for 8bits data width.

///////////////////////////////////////////////////////////////////////
// File:  CRC8_D8.v                             
// Date:  Tue May  3 12:56:07 2005                                                      
//                                                                     
// Copyright (C) 1999-2003 Easics NV.                 
// This source file may be used and distributed without restriction    
// provided that this copyright statement is not removed from the file 
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
//   * polynomial: (0 1 2 8)
//   * data width: 8
//                                                                     
// Info: tools@easics.be
//       http://www.easics.com                                  
///////////////////////////////////////////////////////////////////////


//Add interface for test May.4.2005 Tak.Sugawara

module  CRC8_D8_Module #(parameter integer initial_value=-1, poly_width=8,data_width=8) (input clock,
                                             input [data_width-1:0] data,
                                             input sync_reset,hold,
                                             output reg [poly_width-1:0] crc);

        always @(posedge clock) begin
          if (sync_reset) crc <=initial_value;
                else if (hold) crc <=crc;
                else crc<=nextCRC8_D8(data,crc);
        end

  // polynomial: (0 1 2 8)
  // data width: 8
  // convention: the first serial data bit is D[7]
  function [7:0] nextCRC8_D8;

    input [7:0] Data;
    input [7:0] CRC;

    reg [7:0] D;
    reg [7:0] C;
    reg [7:0] NewCRC;

  begin

    D = Data;
    C = CRC;

    NewCRC[0] = D[7] ^ D[6] ^ D[0] ^ C[0] ^ C[6] ^ C[7];
    NewCRC[1] = D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[1] ^ C[6];
    NewCRC[2] = D[6] ^ D[2] ^ D[1] ^ D[0] ^ C[0] ^ C[1] ^ C[2] ^ C[6];
    NewCRC[3] = D[7] ^ D[3] ^ D[2] ^ D[1] ^ C[1] ^ C[2] ^ C[3] ^ C[7];
    NewCRC[4] = D[4] ^ D[3] ^ D[2] ^ C[2] ^ C[3] ^ C[4];
    NewCRC[5] = D[5] ^ D[4] ^ D[3] ^ C[3] ^ C[4] ^ C[5];
    NewCRC[6] = D[6] ^ D[5] ^ D[4] ^ C[4] ^ C[5] ^ C[6];
    NewCRC[7] = D[7] ^ D[6] ^ D[5] ^ C[5] ^ C[6] ^ C[7];

    nextCRC8_D8 = NewCRC;

  end

  endfunction

endmodule
module CRC8D8_test_bench;
                parameter integer initial_value=-1;
                parameter integer poly_width=8;
                parameter integer data_width=poly_width;
                parameter integer maximum_no_of_errors=6;
                parameter integer data_length=10;
        
                reg clock=0;
                reg sync_reset=1;
                reg hold=0, receiver_hold=0;
                wire [poly_width-1:0] crc_sender,crc_receiver;
                reg done=0;
                integer i,test_loops,error_counter=0;
        
                reg error=0;
                reg [data_width-1:0] data=0;
                wire  [data_width-1:0] receive_data=data^ error;
        

        always #10 clock=~clock;

        initial begin
                        #5;
                        test_loops=0;
//Test 1 Make sure no crc error occurs
                        repeat (100) begin
                                test_loops=test_loops+1;
                                if (test_loops%100==0) $display("Test Loops=%d",test_loops);
                                
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        @(negedge clock);
                                end
                                hold=1;
                                for (i=0;i<1;i=i+1) begin
                                        data=crc_sender[poly_width-1-data_width*i  -:data_width];
                                        @(negedge clock);
                                end
                        
                                done=1;
                                if (crc_receiver !==0) $display("Miss Detectio or Programming Error");
                                @(negedge clock);
                                done=0;
                        end
//Make sure crc error occurs
                        test_loops=0;
                        repeat (1000) begin
                                test_loops=test_loops+1;
                                if (test_loops%1000==0) $display("Test Loops=%d",test_loops);
                        
                                sync_reset=1; 
                                @(negedge clock);
                                @(negedge clock);
                                sync_reset=0; hold=0;error_counter=0;
                                for (i=0;i<data_length;i=i+1) begin
                                        data=$random;
                                        if (i==0) begin
                                                error=1;//We add at least one error. 
                                                error_counter=error_counter+1;
                                        end else begin//Limit maxinum no of errors
                                                if (error_counter <maximum_no_of_errors) begin
                                                        error=$random;//$random error addition
                                                        error_counter=error_counter+1;
                                                end
                                        end
                                        @(negedge clock);
                                end
                                hold=1;//Stop CRC generation in sender
                                for (i=0;i<1;i=i+1) begin
                                        data=crc_sender[poly_width-1-data_width*i  -:data_width];
                                        @(negedge clock);
                                end
                        
                                done=1;
                                if (crc_receiver ==0) $display("Miss Error Detection or Programming Error Test Loops=%d",test_loops);
                                @(negedge clock);
                                done=0;
                        end



                        $finish;
        end


CRC8_D8_Module #(.initial_value(initial_value),.poly_width(poly_width),.data_width(data_width)) crc_sender( clock,
                                                    data,sync_reset,hold,
                                                           crc_sender);

CRC8_D8_Module #(.initial_value(initial_value),.poly_width(poly_width),.data_width(data_width)) crc_receiver( clock,
                                                    receive_data,sync_reset,receiver_hold,
                                                   crc_receiver);

endmodule

4. Notes for implementation
 Some consideration will be necessary for actual implementation.

Miss-synchronization sometimes results successive zero-codeword, which will cause zero-CRC,means success. You can avoid this situation by initializing CRC word not zero.

Note miss-detection probability is not zero by any means of polynomial if raw-error rate is not zero.However it is important to choose appropriate polynomial to suppress miss-detection probability.
For example,you can easily find miss-detection error in small number of loops if random numbers of errors are added in CRC5 . (Miss-detection should never be happened in less than 4 errors addition since CRC5 minimum distance is at least 4 in appropriate code length. )

module CRC5D1_test_bench;
                parameter integer initial_value=-1;
                parameter integer poly_width=5;
                parameter integer maximum_no_of_errors=10;


Download Archive CRC.zip(11KB)