Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

CRC32 implementation in ETHERNET : exact way

Status
Not open for further replies.

dilan2005

Member level 4
Member level 4
Joined
Jul 22, 2007
Messages
75
Helped
8
Reputation
16
Reaction score
2
Trophy points
1,288
Visit site
Activity points
1,837
crc32 ethernet

hi,

i need to know how to get ethernet FCS !

i can implement generic crc32, but there are some other special things to do before data put to the crc32 generator and after gert crc32 checksum out of the generator some bit reversals/complementing


can any one give me a brief point form the process of setup Ethernet packet.
(NO need to explain crc32 gen proccess)

if you can explain following Ethernet packet and how final FCS formed it is much better.
55 55 55 55 55 55 55 D5 //start of frame

00 0A E6 F0 05 A3 00 12 34 56 78 90 08 00 45 00 00 30 B3 FE 00 00 80 11 72 BA 0A 00 00 03 0A 00 00 02 04 00 04 00 00 1C 89 4D 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13

7A D5 6B B3 //frame checksum

Thanks !
regards
dilan
 

ethernet crc32

Try this C program. It assumes 'int' is 32 bits and 'char' is 8 bits.
The program output is: 7A D5 6B B3
Code:
#include <stdio.h>

int main(void)
{
  unsigned char data[] =
  {
    0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
    0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
    0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
    0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
    0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
    0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
    0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
    0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
  };
  unsigned int crc_table[] =
  {
    0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0,
    0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320,
    0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190,
    0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000
  };
  unsigned int n, crc=0;

  for (n=0; n<sizeof(data); n++)
  {
    crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 0)) & 0x0F];  /* lower nibble */
    crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 4)) & 0x0F];  /* upper nibble */
  }
  for (n=0; n<4; n++)  /* display the CRC, lower byte first */
  {
    printf("%02X ", crc & 0xFF);
    crc >>= 8;
  }
  printf("\n");
  return 0;
}
 

    dilan2005

    Points: 2
    Helpful Answer Positive Rating
crc32-ieee802.3

thank you very much echo47, i will go through the code
rgds
dilan
 


ethernet crc implementation

thanks benradu.

the documentaion of anlog devices help much.try out your self step with example and online calucaltor it doesent work.i found that from another forum "CRC32 AUTODIN II" algo must be used.i'dont know above c programme algo name

any way , i tried implement above c code in verilog but it give me wrong answer.can any one check following verilog code for me

Code:
module FCS_CAL(clk,data,enable,crc_out,reset);
input clk;

input [7:0] data;
input enable;
input reset;
	 
output [31:0] crc_out;

	
reg [31:0] crc_out;
reg[3:0] crc_table_adr;
reg[31:0] crc_table_data;

always @(crc_table_adr) begin
	 case (crc_table_adr) 
		4'h0:crc_table_data=32'h4DBDF21C; 
		4'h1:crc_table_data=32'h500AE278; 
		4'h2:crc_table_data=32'h76D3D2D4; 
		4'h3:crc_table_data=32'h6B64C2B0;
		4'h4:crc_table_data=32'h3B61B38C;
		4'h5:crc_table_data=32'h26D6A3E8;
		4'h6:crc_table_data=32'h000F9344;
		4'h7:crc_table_data=32'h1DB88320;
		4'h8:crc_table_data=32'hA005713C;
		4'h9:crc_table_data=32'hBDB26158;
		4'hA:crc_table_data=32'h9B6B51F4; 
		4'hB:crc_table_data=32'h86DC4190;
		4'hC:crc_table_data=32'hD6D930AC; 
		4'hD:crc_table_data=32'hCB6E20C8; 
		4'hE:crc_table_data=32'hEDB71064;
		4'hF:crc_table_data=32'hF0000000;
	 
	 endcase
end
  
	
 always @(posedge clk)begin
	if(reset==1 && enable==0) crc_out=32'h00000000;
   
	
	if(reset==0 && enable==1) begin

	//crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 0)) & 0x0F];  /* lower nibble */
	
	crc_table_adr=crc_out[3:0] ^ data1[3:0]; 
	#100 crc_out=(crc_out>>4)^crc_table_data;
	
	//crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 4)) & 0x0F];  /* upper nibble */
	
	crc_table_adr=crc_out[3:0] ^ data1[7:4]; 
	d_out=crc_table_adr;
	#100 crc_out=(crc_out>>4)^crc_table_data;
	end
	
	end
endmodule

if there any thing wrong in the implementation please correct me

Thank you

regards
dilan

Added after 57 seconds:

thanks benradu.

the documentaion of anlog devices help much.try out your self step with example and online calucaltor it doesent work.i found that from another forum "CRC32 AUTODIN II" algo must be used.i'dont know above c programme algo name

any way , i tried implement above c code in verilog but it give me wrong answer.can any one check following verilog code for me

Code:
module FCS_CAL(clk,data,enable,crc_out,reset);
input clk;

input [7:0] data;
input enable;
input reset;
	 
output [31:0] crc_out;

	
reg [31:0] crc_out;
reg[3:0] crc_table_adr;
reg[31:0] crc_table_data;

always @(crc_table_adr) begin
	 case (crc_table_adr) 
		4'h0:crc_table_data=32'h4DBDF21C; 
		4'h1:crc_table_data=32'h500AE278; 
		4'h2:crc_table_data=32'h76D3D2D4; 
		4'h3:crc_table_data=32'h6B64C2B0;
		4'h4:crc_table_data=32'h3B61B38C;
		4'h5:crc_table_data=32'h26D6A3E8;
		4'h6:crc_table_data=32'h000F9344;
		4'h7:crc_table_data=32'h1DB88320;
		4'h8:crc_table_data=32'hA005713C;
		4'h9:crc_table_data=32'hBDB26158;
		4'hA:crc_table_data=32'h9B6B51F4; 
		4'hB:crc_table_data=32'h86DC4190;
		4'hC:crc_table_data=32'hD6D930AC; 
		4'hD:crc_table_data=32'hCB6E20C8; 
		4'hE:crc_table_data=32'hEDB71064;
		4'hF:crc_table_data=32'hF0000000;
	 
	 endcase
end
  
	
 always @(posedge clk)begin
	 if(reset==1 && enable==0) crc_out=32'h00000000;
   
	
	if(reset==0 && enable==1) begin

	        //crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 0)) & 0x0F];  /* lower nibble */
	
	       crc_table_adr=crc_out[3:0] ^ data1[3:0]; 
	      #100 crc_out=(crc_out>>4)^crc_table_data;
	
	      //crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 4)) & 0x0F];  /* upper nibble */
	
	     crc_table_adr=crc_out[3:0] ^ data1[7:4]; 
	     d_out=crc_table_adr;
	    #100 crc_out=(crc_out>>4)^crc_table_data;
	end
	
	end
endmodule

if there any thing wrong in the implementation please correct me

Thank you

regards
dilan

Added after 10 minutes:

some mistakes in above code .following is the right code.

Code:
module FCS_CAL(clk,data,enable,crc_out,reset);
input clk;

input [7:0] data;
input enable;
input reset;
	 
output [31:0] crc_out;

	
reg [31:0] crc_out;
reg[3:0] crc_table_adr;
reg[31:0] crc_table_data;

always @(crc_table_adr) begin
	 case (crc_table_adr) 
		4'h0:crc_table_data=32'h4DBDF21C; 
		4'h1:crc_table_data=32'h500AE278; 
		4'h2:crc_table_data=32'h76D3D2D4; 
		4'h3:crc_table_data=32'h6B64C2B0;
		4'h4:crc_table_data=32'h3B61B38C;
		4'h5:crc_table_data=32'h26D6A3E8;
		4'h6:crc_table_data=32'h000F9344;
		4'h7:crc_table_data=32'h1DB88320;
		4'h8:crc_table_data=32'hA005713C;
		4'h9:crc_table_data=32'hBDB26158;
		4'hA:crc_table_data=32'h9B6B51F4; 
		4'hB:crc_table_data=32'h86DC4190;
		4'hC:crc_table_data=32'hD6D930AC; 
		4'hD:crc_table_data=32'hCB6E20C8; 
		4'hE:crc_table_data=32'hEDB71064;
		4'hF:crc_table_data=32'hF0000000;
	 
	 endcase
end
  
	
 always @(posedge clk)begin
	if(reset==1 && enable==0) begin
	crc_out=32'h00000000;
   end
	
	if(reset==0 && enable==1) begin
		//crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 0)) & 0x0F];  /* lower nibble */
		
		crc_table_adr=crc_out[3:0] ^ data[3:0]; 
		#100 crc_out=(crc_out>>4)^crc_table_data;
		
		//crc = (crc >> 4) ^ crc_table[(crc ^ (data[n] >> 4)) & 0x0F];  /* upper nibble */
		
		crc_table_adr=crc_out[3:0] ^ data[7:4]; 
		#100 crc_out=(crc_out>>4)^crc_table_data;
	end
	
	end
endmodule

please check above code
 

crc32 c implementation ieee802.3

sorry but I don't know too much verilog.
I used the CRC tool (the third link that I gave you) to generate a vhdl package.
I used this in a project and works great.
The online crc calculation tool also works OK for me. I use it all the time I need to double check a CRC.
here is the vhdl package
Code:
-----------------------------------------------------------------------
-- File:  PCK_CRC32_D8.vhd                              
-- Date:  Mon Oct 29 15:04:32 2007                                                      
--                                                                     
-- 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: VHDL package containing a synthesizable CRC function
--   * polynomial: (0 1 2 4 5 7 8 10 11 12 16 22 23 26 32)
--   * data width: 8
--                                                                     
-- Info: [email]tools@easics.be[/email]
--       [url]https://www.easics.com[/url]                                  
-----------------------------------------------------------------------


library IEEE;
use IEEE.std_logic_1164.all;

package PCK_CRC32_D8 is

  -- polynomial: (0 1 2 4 5 7 8 10 11 12 16 22 23 26 32)
  -- data width: 8
  -- convention: the first serial data bit is D(7)
  function nextCRC32_D8
    ( Data:  std_logic_vector(7 downto 0);
      CRC:   std_logic_vector(31 downto 0) )
    return std_logic_vector;

end PCK_CRC32_D8;

library IEEE;
use IEEE.std_logic_1164.all;

package body PCK_CRC32_D8 is

  -- polynomial: (0 1 2 4 5 7 8 10 11 12 16 22 23 26 32)
  -- data width: 8
  -- convention: the first serial data bit is D(7)
  function nextCRC32_D8  
    ( Data:  std_logic_vector(7 downto 0);
      CRC:   std_logic_vector(31 downto 0) )
    return std_logic_vector is

    variable D: std_logic_vector(7 downto 0);
    variable C: std_logic_vector(31 downto 0);
    variable NewCRC: std_logic_vector(31 downto 0);

  begin

    D := Data;
    C := CRC;

    NewCRC(0) := D(6) xor D(0) xor C(24) xor C(30);
    NewCRC(1) := D(7) xor D(6) xor D(1) xor D(0) xor C(24) xor C(25) xor 
                 C(30) xor C(31);
    NewCRC(2) := D(7) xor D(6) xor D(2) xor D(1) xor D(0) xor C(24) xor 
                 C(25) xor C(26) xor C(30) xor C(31);
    NewCRC(3) := D(7) xor D(3) xor D(2) xor D(1) xor C(25) xor C(26) xor 
                 C(27) xor C(31);
    NewCRC(4) := D(6) xor D(4) xor D(3) xor D(2) xor D(0) xor C(24) xor 
                 C(26) xor C(27) xor C(28) xor C(30);
    NewCRC(5) := D(7) xor D(6) xor D(5) xor D(4) xor D(3) xor D(1) xor 
                 D(0) xor C(24) xor C(25) xor C(27) xor C(28) xor C(29) xor 
                 C(30) xor C(31);
    NewCRC(6) := D(7) xor D(6) xor D(5) xor D(4) xor D(2) xor D(1) xor 
                 C(25) xor C(26) xor C(28) xor C(29) xor C(30) xor C(31);
    NewCRC(7) := D(7) xor D(5) xor D(3) xor D(2) xor D(0) xor C(24) xor 
                 C(26) xor C(27) xor C(29) xor C(31);
    NewCRC(8) := D(4) xor D(3) xor D(1) xor D(0) xor C(0) xor C(24) xor 
                 C(25) xor C(27) xor C(28);
    NewCRC(9) := D(5) xor D(4) xor D(2) xor D(1) xor C(1) xor C(25) xor 
                 C(26) xor C(28) xor C(29);
    NewCRC(10) := D(5) xor D(3) xor D(2) xor D(0) xor C(2) xor C(24) xor 
                  C(26) xor C(27) xor C(29);
    NewCRC(11) := D(4) xor D(3) xor D(1) xor D(0) xor C(3) xor C(24) xor 
                  C(25) xor C(27) xor C(28);
    NewCRC(12) := D(6) xor D(5) xor D(4) xor D(2) xor D(1) xor D(0) xor 
                  C(4) xor C(24) xor C(25) xor C(26) xor C(28) xor C(29) xor 
                  C(30);
    NewCRC(13) := D(7) xor D(6) xor D(5) xor D(3) xor D(2) xor D(1) xor 
                  C(5) xor C(25) xor C(26) xor C(27) xor C(29) xor C(30) xor 
                  C(31);
    NewCRC(14) := D(7) xor D(6) xor D(4) xor D(3) xor D(2) xor C(6) xor 
                  C(26) xor C(27) xor C(28) xor C(30) xor C(31);
    NewCRC(15) := D(7) xor D(5) xor D(4) xor D(3) xor C(7) xor C(27) xor 
                  C(28) xor C(29) xor C(31);
    NewCRC(16) := D(5) xor D(4) xor D(0) xor C(8) xor C(24) xor C(28) xor 
                  C(29);
    NewCRC(17) := D(6) xor D(5) xor D(1) xor C(9) xor C(25) xor C(29) xor 
                  C(30);
    NewCRC(18) := D(7) xor D(6) xor D(2) xor C(10) xor C(26) xor C(30) xor 
                  C(31);
    NewCRC(19) := D(7) xor D(3) xor C(11) xor C(27) xor C(31);
    NewCRC(20) := D(4) xor C(12) xor C(28);
    NewCRC(21) := D(5) xor C(13) xor C(29);
    NewCRC(22) := D(0) xor C(14) xor C(24);
    NewCRC(23) := D(6) xor D(1) xor D(0) xor C(15) xor C(24) xor C(25) xor 
                  C(30);
    NewCRC(24) := D(7) xor D(2) xor D(1) xor C(16) xor C(25) xor C(26) xor 
                  C(31);
    NewCRC(25) := D(3) xor D(2) xor C(17) xor C(26) xor C(27);
    NewCRC(26) := D(6) xor D(4) xor D(3) xor D(0) xor C(18) xor C(24) xor 
                  C(27) xor C(28) xor C(30);
    NewCRC(27) := D(7) xor D(5) xor D(4) xor D(1) xor C(19) xor C(25) xor 
                  C(28) xor C(29) xor C(31);
    NewCRC(28) := D(6) xor D(5) xor D(2) xor C(20) xor C(26) xor C(29) xor 
                  C(30);
    NewCRC(29) := D(7) xor D(6) xor D(3) xor C(21) xor C(27) xor C(30) xor 
                  C(31);
    NewCRC(30) := D(7) xor D(4) xor C(22) xor C(28) xor C(31);
    NewCRC(31) := D(5) xor C(23) xor C(29);

    return NewCRC;

  end nextCRC32_D8;

end PCK_CRC32_D8;
and here is how I use this
Code:
process(clk_i)
      variable i_nextCRC32_D8 : std_logic_vector(31 downto 0);
   begin
      if rising_edge(clk_i) then
         if rst_i = '1' then
            i_crc <= (others=>'1');
             match_o <= '0';
         elsif clken_i = '1' then
            i_nextCRC32_D8 := nextCRC32_D8(data_r, i_crc);
            i_crc <= i_nextCRC32_D8;

            if i_nextCRC32_D8 = 0 then
               match_o <= '1';
            else
               match_o <= '0';
            end if;

         end if;
      end if;
   end process;
 
online ethernet crc calculator

Hi dilan2005, I don't have time right now to study your code, sorry, but those '=' blocking assignments and #100 delays are not good synthesizable Verilog style. Try writing totally synchronous code, and maybe the problem will disappear. Good luck.
 

ethernet crc32 packet

thanks everyone helping me on this.sick of crc now and try to do the bussiness the original way .IEEE802.3 specification section 1 ,



i wrote following code for testing


Code:
`timescale 1ns / 1ps

module cccc(clk, CRC_out);
	input clk;
	output [31:0] CRC_out;
	reg [31:0] CRC_out;
	reg[32:0] CRCPoly ;
	reg[32:0] CRC,crc_temp ;
	reg [7:0] j,k;
	reg [15:0] temp_buf;
	reg [7:0] Inbuff[90:0];
	reg first_time;
	
	always @(posedge clk) begin
		
			  
		Inbuff[0]=8'h55;
		Inbuff[1]=8'h55;
		Inbuff[2]=8'h55;
		Inbuff[3]=8'h55;
		Inbuff[4]=8'h55;
		Inbuff[5]=8'h55;
		Inbuff[6]=8'h55;
		Inbuff[7]=8'hD5;
		
		Inbuff[8]=8'h00;//not inverted FF
		Inbuff[9]=8'h0A;	// not inveted AF 
		Inbuff[10]=8'hE6; //~ inverterd 98
		Inbuff[11]=8'hF0;//~ inverted F0
		
		Inbuff[12]=8'h05;
		Inbuff[13]=8'hA3;
		Inbuff[14]=8'h00;
		Inbuff[15]=8'h12;
		Inbuff[16]=8'h34;
		Inbuff[17]=8'h56;
		Inbuff[18]=8'h78;
		Inbuff[19]=8'h90;
		Inbuff[20]=8'h08;
		Inbuff[21]=8'h00;
		Inbuff[22]=8'h45;
		Inbuff[23]=8'h00;
		Inbuff[24]=8'h00;
		Inbuff[25]=8'h30;
		Inbuff[26]=8'hB3;
		Inbuff[27]=8'hFE;
		Inbuff[28]=8'h00;
		Inbuff[29]=8'h00;
		Inbuff[30]=8'h80;
		Inbuff[31]=8'h11;
		Inbuff[32]=8'h72;
		Inbuff[33]=8'hBA;
		Inbuff[34]=8'h0A;
		Inbuff[35]=8'h00;
		Inbuff[36]=8'h00;
		Inbuff[37]=8'h03;
		Inbuff[38]=8'h0A;
		Inbuff[39]=8'h00;
		Inbuff[40]=8'h00;
		Inbuff[41]=8'h02;
		Inbuff[42]=8'h04;
		Inbuff[43]=8'h00;
		Inbuff[44]=8'h04;
		Inbuff[45]=8'h00;
		Inbuff[46]=8'h00;
		Inbuff[47]=8'h1C;
		Inbuff[48]=8'h89;
		Inbuff[49]=8'h4D;
		Inbuff[50]=8'h00;
		Inbuff[51]=8'h01;
		Inbuff[52]=8'h02;
		Inbuff[53]=8'h03;
		Inbuff[54]=8'h04;
		Inbuff[55]=8'h05;
		Inbuff[56]=8'h06;
		Inbuff[57]=8'h07;
		Inbuff[58]=8'h08;
		Inbuff[59]=8'h09;
		Inbuff[60]=8'h0A;
		Inbuff[61]=8'h0B;
		Inbuff[62]=8'h0C;
		Inbuff[63]=8'h0D;
		Inbuff[64]=8'h0E;
		Inbuff[65]=8'h0F;
		Inbuff[66]=8'h10;
		Inbuff[67]=8'h11;
		Inbuff[68]=8'h12;
		Inbuff[69]=8'h13;
		Inbuff[70]=8'h00;
		Inbuff[71]=8'h00;//7AD5;
		Inbuff[72]=8'h00;
		Inbuff[73]=8'h00;//6BB3;

		CRCPoly =33'b100000100110000010001110110110111;
		CRC[32:0]=33'h0FFAF98F0; //IEEE asked to complement 32bits before putting to the CRC generator
		
		
			for (j=12;j<=69;j=j+1) begin
				for (k=0;k<=7;k=k+1)  begin  					
               temp_buf=Inbuff[j];
					
					CRC={CRC[32:1],temp_buf[k]}; //LSB put to the crc gen first
			
					if(CRC[32]==1'b1) 	CRC = CRC ^ CRCPoly;
				end 
			end
		CRC_out=~CRC[31:0];
end
endmodule


but the out is following 0x50670F

what is the wrong of my code!
:cry:

please Help me , thanks

dilan
 

crc32 ieee802.3

I didn't study your cccc module, but those 'for' loops are trying to compute the CRC of the entire packet in one clock cycle.

Try this Verilog version of my C example. The 'ready' pulse identifies the final CRC value:
Code:
module top (clk, crc, ready);
  input                 clk;
  reg             [7:0] data [0:69];
  reg             [6:0] addr = 8;
  wire           [31:0] crc1, crc2;
  output reg     [31:0] crc = 0;
  output reg            ready = 0;

  initial begin
    data[0]=8'h55;  data[1]=8'h55;  data[2]=8'h55;  data[3]=8'h55;
    data[4]=8'h55;  data[5]=8'h55;  data[6]=8'h55;  data[7]=8'hD5;
    data[8]=8'h00;  data[9]=8'h0A;  data[10]=8'hE6; data[11]=8'hF0;
    data[12]=8'h05; data[13]=8'hA3; data[14]=8'h00; data[15]=8'h12;
    data[16]=8'h34; data[17]=8'h56; data[18]=8'h78; data[19]=8'h90;
    data[20]=8'h08; data[21]=8'h00; data[22]=8'h45; data[23]=8'h00;
    data[24]=8'h00; data[25]=8'h30; data[26]=8'hB3; data[27]=8'hFE;
    data[28]=8'h00; data[29]=8'h00; data[30]=8'h80; data[31]=8'h11;
    data[32]=8'h72; data[33]=8'hBA; data[34]=8'h0A; data[35]=8'h00;
    data[36]=8'h00; data[37]=8'h03; data[38]=8'h0A; data[39]=8'h00;
    data[40]=8'h00; data[41]=8'h02; data[42]=8'h04; data[43]=8'h00;
    data[44]=8'h04; data[45]=8'h00; data[46]=8'h00; data[47]=8'h1C;
    data[48]=8'h89; data[49]=8'h4D; data[50]=8'h00; data[51]=8'h01;
    data[52]=8'h02; data[53]=8'h03; data[54]=8'h04; data[55]=8'h05;
    data[56]=8'h06; data[57]=8'h07; data[58]=8'h08; data[59]=8'h09;
    data[60]=8'h0A; data[61]=8'h0B; data[62]=8'h0C; data[63]=8'h0D;
    data[64]=8'h0E; data[65]=8'h0F; data[66]=8'h10; data[67]=8'h11;
    data[68]=8'h12; data[69]=8'h13;
  end

  function [31:0] crc_table;
    input [3:0] addr;
    case (addr)
       0: crc_table = 32'h4DBDF21C;
       1: crc_table = 32'h500AE278;
       2: crc_table = 32'h76D3D2D4;
       3: crc_table = 32'h6B64C2B0;
       4: crc_table = 32'h3B61B38C;
       5: crc_table = 32'h26D6A3E8;
       6: crc_table = 32'h000F9344;
       7: crc_table = 32'h1DB88320;
       8: crc_table = 32'hA005713C;
       9: crc_table = 32'hBDB26158;
      10: crc_table = 32'h9B6B51F4;
      11: crc_table = 32'h86DC4190;
      12: crc_table = 32'hD6D930AC;
      13: crc_table = 32'hCB6E20C8;
      14: crc_table = 32'hEDB71064;
      15: crc_table = 32'hF0000000;
      default: crc_table = 32'bx;
    endcase
  endfunction

  assign crc1 = crc[31:4]  ^ crc_table(crc[3:0]  ^ data[addr][3:0]);
  assign crc2 = crc1[31:4] ^ crc_table(crc1[3:0] ^ data[addr][7:4]);

  always @ (posedge clk) begin
    crc  <= crc2;
    addr <= addr + 1;
    ready <= (addr == 69);
  end
endmodule
This code should synthesize fine, but I didn't try to optimize it.
 

    dilan2005

    Points: 2
    Helpful Answer Positive Rating
crc32 implementation in c

thanks.:D echo47 it works great:D.i will able to finish my udp packet tx part today.

as i go through your code i feel that i am missing some coding practices.is there any way to improve my verilog coding style.(books,sites)

Thanks
rgds
dilan
 

ieee 802.3 crc implementation

finally able write my simple Ethernet MAC tx module with crc.i really apprciate support given by guys on the forum. my special thanks to echo47 using his his verilog code i was able to generate crc on the fly.and put the result in to PHY.i will post my cleaned verilog source code of my simple eth tx soon.
 

Re: crc32 ieee802.3

Hi,
can you please explain/website link the algorithm to compute this crc as from implementation point of view its great but kindly guide me the logic behind it.
BR
aLI
 

The CRC is usually explained as polynomial division in "GF2[x]". eg, polynomials with coefficients of 0 or 1, where 0+0=0, 0+1=1, 1+1=0, and 0*0=0, 0*1=0, 1*1=1.

to divide 10000 by 101 you'd do:
1_0000 xor 10100 = 00100 (_ is just used as a visual aid). to cancel out this leading 1, add 10100
00_100 xor 00000 = 00100 the digit before the _ is 0, so there is no need to add 01010
001_00 xor 00101 = 00001 the digit before the _ is 1, so ass 00101
the remainder is 00001.

if you convert these into polynomials, you have x^4 / (x^2+1).
x^4 + (x^2+1)*x^2 = x^2 (as before, in GF2, 1+1=0)
x^2 + (x^2+1)*0*x = x^2
x^2 + (x^2+1)*1 = 1
to check, (x^2+1) * (x^2+1) + 1 = x^4 + x^2 + x^2 + 1 + 1 = x^4. (the quotient above was x^2+1, and again, 1+1=x^2+x^2=0)

the CRC uses a specific divisor, and can also have some constant added to the result or the data. this is because the CRC isn't good for detecting missing leading zeros.

The intention of the CRC is to improve upon simple checksums. for example, a 2's complement checksum can always detect 1 bit error, but if the msb is in error twice, that error will not be detected. the CRC tends to be very good at detecting errors. Further, the CRC results in very simple hardware for serial data -- as shown above it is basically just xor gates that get applied if the input bit is 1. The specific divisors for a CRC are carefully chosen (the above example was arbitrary).

The other implementations in the post are methods for performing the above algorithm that work better on a computer or system that gets 8b at a time.
 

Hi to all, I'm new to this forum and i found the code suggested by echo47 great but I want to implement this CRC calculation in a Big Endian architecture (this code works only for little endian). Any suggestion on how to change the code for fitting it in a Big endian machine? I search in the web but I didn't find any algorithm that use this small 16-entries table.

Thanks a lot.
 

You can find explanations and an online CRC calculator here:

On-line CRC calculation and free library

When I paste your sequence into the window and press "hex" and "calculate", it gives "0xB36BD57A" for CRC-32.
That is your wanted "frame checksum" in reverse byte order.

If you want efficient implementations in VHDL or Verilog, look here:

Easics
 

Thank you for the replies, but all the code that i've found works great on a little-endian arch. I want a simple c algorithm that works on a Big-endian machine because i cannot use the 256-entries table because i haven't enough memory; but using a 16 entries table, as the code proposed by echo47 does, is fine for my task. I ask you if there is a chance to modify the code proposed by echo47 to make it works on a big-endian architecture.

Thanks a lot.
 

You can find explanations and an online CRC calculator here:

On-line CRC calculation and free library

When I paste your sequence into the window and press "hex" and "calculate", it gives "0xB36BD57A" for CRC-32.
That is your wanted "frame checksum" in reverse byte order.

If you want efficient implementations in VHDL or Verilog, look here:

Easics

I now see that user "benradu" already have linked to both these sites earlier in the thread.

Anyone that is going to implement CRC in hardware (VHDL, Verilog) should NOT try to port a software implementation. An efficient hardware implementation is just a bunch of XOR gates, working on individual bits. Software can't do that efficiently, so it is normally done using tricks that are completely meaningless for a hardware implementation. You will only get confused if you start with a software implementation. Look at the code generated by the easics page and you will understand how it should be done in hardware.
 

I now see that user "benradu" already have linked to both these sites earlier in the thread.

Anyone that is going to implement CRC in hardware (VHDL, Verilog) should NOT try to port a software implementation. An efficient hardware implementation is just a bunch of XOR gates, working on individual bits. Software can't do that efficiently, so it is normally done using tricks that are completely meaningless for a hardware implementation. You will only get confused if you start with a software implementation. Look at the code generated by the easics page and you will understand how it should be done in hardware.

I'm not going to do crc32 by hardware but i have to do it by sofware, and i want to do that in a big endian arch with few memory.
 

Sounds easy enough to do. And if you don't want to do it yourself, simply googling "crc32 big endian" turns up plenty of information. For example https://code.haskell.org/zlib/cbits/crc32.c handles both big and little endian. This was all of 10 seconds worth of work. You're welcome. :p

PS: If this C code is not exactly what you're looking for I suggest something like doing 120 seconds of work to find source code that does conform to your specifications.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top