Simulating CRC32 according to IEEE Std. 802.3

Discussion in 'VHDL' started by ALuPin, Dec 14, 2005.

  1. ALuPin

    ALuPin Guest

    Hi,

    I have been googling for a while
    having noticed that there is no clear answer to my following problem:

    The IEEE Std. 802.3 says the following: (section 3.2.8 Frame Check
    Sequence field)

    I use the following CRC32-VHDL module:

    -- File: PCK_CRC32_D8.vhd
    -- 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:

    Now I want to simulate the CRC according to the IEEE standard. I have a
    transmitter including the CRC32
    module and a receiver including the CRC32 module.
    But I have some doubts on how to perform a conform simulation.

    Let's assume that the following bytes are transmitted via Ethernet(one
    byte interface), they are fed into the easics- module:
    byte0 = "00000000" (Integer 0)
    byte1 = "00000001" (Integer 1)
    ....
    byte255="11111111" (Integer 255)

    Are the following assumptions correct ?

    1. The CRC has to be initialized to
    NOT ("00000011 00000010 00000001 00000000")

    2. The calculated CRC has to be inverted and appended in the following
    manner:
    first byte appendix: NOT CRC(31 DOWNTO 24)
    second byte appendix NOT CRC(23 DOWNTO 16)
    third byte appendix NOT CRC(15 DOWNTO 8)
    fourth byte appendix NOT CRC(7 DOWNTO 0)

    3. To which value do I have to reset the "remote" CRC module ?

    4. Do I have to remove the CRC32 appendix of the Ethernet packets and
    replace the four bytes with "00000000" ?

    I would be very thankful if you could shed some light on it.

    Rgds
    André
     
    ALuPin, Dec 14, 2005
    #1
    1. Advertisements

  2. ALuPin

    Sudhir.Singh Guest

    Hi André

    I have just completed a 802.3 implementation and I think I can give you
    some answers.
    First of all my CRC implementation was based on the following paper "A
    Symbol Based Algorithm for Hardware Implementation of CRC", R. Nair, G.
    Ryan and F Farzaneh.
    This implementation uses xor equations to calculate CRC.
    In this case the CRC is reset to zero before commencing a new
    computation.

    2) The final output needs to be bit reversed and inverted i.e
    for i in 31 downto 0 loop
    CRC(i) <= not CRCReg(31 - i);
    end loop;
    3) On the receiver you pass the whole packet through the CRC generator
    including the CRC.
    The result in the CRC register after the last byte has gone through
    is called the residue, and in the
    case of 802.3 it is 0xC704DD7B if there are no errors. All you need
    to do is compare the CRC register
    with the residue. Note that this is not the bit reversed and
    inverted value.

    Hope this will help
    Sudhir
     
    Sudhir.Singh, Dec 16, 2005
    #2
    1. Advertisements

  3. ALuPin

    ALuPin Guest

    Hi Sudhir,

    thank you for detailed answer.

    If I do that the manner you describe I also get that residuum when
    using the easics-module (CRC-Reset Value (OTHERS => '1')).

    But I wonder what the IEEE Std. 802.3 (section 3.2.8 Frame Check
    Sequence field)

    means when claiming
    a)The ï¬rst 32 bits of the frame are complemented.

    Do you have any idea ?

    Rgds
    André
     
    ALuPin, Dec 16, 2005
    #3
  4. It means exactly what it says. You invert the first 32 bits of the
    frame.

    I listed a number of CRC properties in this thread:
    http://groups.google.com/group/comp...4d0fc43dbc1/cf1e7d94dedc5733#cf1e7d94dedc5733
    Property 3 says:
    " Initialising the register to all ones is equivalent to initialising
    the register to all zeros and *inverting the first N bits of the
    message*."

    Regards,
    Allan
     
    allanherriman, Dec 16, 2005
    #4
  5. It means exactly what it says. You invert the first 32 bits of the
    Note that you get the same results if you initialize the CRC register
    with all ones and do not complement the first 32 bits, due to the
    properties of the CRC algorithm.

    Inverting the first 32 bits (or equivalently using a start valuie of
    0xFFFFFFFF) detects erroneous 0s inside the start sequence (first 32
    bits). If you initialize with 0 and have additional 0s at the
    beginning, standard CRC will not detect it (CRC uses polynom division,
    dividing 0 always gives 0).

    Hubble.
     
    Reiner Huober, Dec 16, 2005
    #5
  6. ALuPin

    ALuPin Guest

    Hi Allan, hi Reiner,

    thank you for your responses. They have shed some light on my problem.

    I have simulated the test design with respect to your considerations
    and they
    are correct.

    Thanks again for your help.

    Rgds
    André
     
    ALuPin, Dec 16, 2005
    #6
  7. ALuPin

    ALuPin Guest

    Hi Sudhir,
    Yes, the simulation shows that.

    Rgds
    André
     
    ALuPin, Dec 16, 2005
    #7
  8. ALuPin

    AK51

    Joined:
    Dec 29, 2008
    Messages:
    3
    Likes Received:
    0
    Hi, I can get the first byte working for 8 bits input into CRC32.
    However, the second byte gives me wrong CRC.
    Here is what I did.
    1. reverse the bit order for the 8 bits input
    2. For the CRC output, 'not' and 'reverse' the bit order.
    I got the first byte correct 'coz the initialization is "FFFF". Right now, I just feed the NEW CRC[31..0] directly back to C[31..0], should I modify this path before I feed it back to the C[31..0]? Thx
     
    AK51, Dec 29, 2008
    #8
  9. ALuPin

    AK51

    Joined:
    Dec 29, 2008
    Messages:
    3
    Likes Received:
    0
    I use this website to verify my CRC
    w w w.lammertbies.nl/comm/info/crc-calculation.html?crc=031c&method=hex
    It shows 0x7EF51D73
    But I got 0x55D84EB0

    Thx.
     
    AK51, Dec 29, 2008
    #9
  10. ALuPin

    TomoP

    Joined:
    Apr 14, 2009
    Messages:
    1
    Likes Received:
    0
    CRC32 8 bit VHDL

    Here is my code, if someone will need it. I have checked my results with HashCalc software and on the website mentioned above. The XOR formulas were generated on this site: ipgeniuscores.com/ipgenius.php?module=CRC_generator
    I made it this way:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity crcgenerator_i8b is
    Port (
    RST: in STD_LOGIC;
    CLK: in STD_LOGIC;
    GENER_CRC: in STD_LOGIC;
    TX_DATA: in STD_LOGIC_VECTOR (7 downto 0);
    TXD: out STD_LOGIC_VECTOR (31 downto 0)

    );
    end crcgenerator_i8b;

    architecture crcgenerator_i8b_arch of crcgenerator_i8b is
    constant CRC_INIT_VALUE: STD_LOGIC_VECTOR (31 downto 0) := X"FFFF_FFFF";

    type CRC_STATE_type is (IDLE, RUN, STOP);
    signal STATE: CRC_STATE_type;
    signal CRC_BUF: STD_LOGIC_VECTOR (0 to 31); --!!! Important

    function COUNT_CRC (d: STD_LOGIC_VECTOR (0 to 7); --!!! Important
    c: STD_LOGIC_VECTOR (31 downto 0))
    return STD_LOGIC_VECTOR is
    variable new_crc: STD_LOGIC_VECTOR (31 downto 0);
    begin
    new_crc(0) := D(6) XOR D(0) XOR C(30) XOR C(24);
    new_crc(1) := D(7) XOR D(6) XOR D(1) XOR D(0) XOR C(31) XOR C(30) XOR C(25) XOR C(24);
    new_crc(2) := D(7) XOR D(6) XOR D(2) XOR D(1) XOR D(0) XOR C(31) XOR C(30) XOR C(26) XOR C(25) XOR C(24);
    new_crc(3) := D(7) XOR D(3) XOR D(2) XOR D(1) XOR C(31) XOR C(27) XOR C(26) XOR C(25);
    new_crc(4) := D(6) XOR D(4) XOR D(3) XOR D(2) XOR D(0) XOR C(30) XOR C(28) XOR C(27) XOR C(26) XOR C(24);
    new_crc(5) := D(7) XOR D(6) XOR D(5) XOR D(4) XOR D(3) XOR D(1) XOR D(0) XOR C(31) XOR C(30) XOR C(29) XOR C(28) XOR C(27) XOR C(25) XOR C(24);
    new_crc(6) := D(7) XOR D(6) XOR D(5) XOR D(4) XOR D(2) XOR D(1) XOR C(31) XOR C(30) XOR C(29) XOR C(28) XOR C(26) XOR C(25);
    new_crc(7) := D(7) XOR D(5) XOR D(3) XOR D(2) XOR D(0) XOR C(31) XOR C(29) XOR C(27) XOR C(26) XOR C(24);
    new_crc(8) := D(4) XOR D(3) XOR D(1) XOR D(0) XOR C(28) XOR C(27) XOR C(25) XOR C(24) XOR C(0);
    new_crc(9) := D(5) XOR D(4) XOR D(2) XOR D(1) XOR C(29) XOR C(28) XOR C(26) XOR C(25) XOR C(1);
    new_crc(10) := D(5) XOR D(3) XOR D(2) XOR D(0) XOR C(2) XOR C(29) XOR C(27) XOR C(26) XOR C(24);
    new_crc(11) := D(4) XOR D(3) XOR D(1) XOR D(0) XOR C(3) XOR C(28) XOR C(27) XOR C(25) XOR C(24);
    new_crc(12) := D(6) XOR D(5) XOR D(4) XOR D(2) XOR D(1) XOR D(0) XOR C(4) XOR C(30) XOR C(29) XOR C(28) XOR C(26) XOR C(25) XOR C(24);
    new_crc(13) := D(7) XOR D(6) XOR D(5) XOR D(3) XOR D(2) XOR D(1) XOR C(5) XOR C(31) XOR C(30) XOR C(29) XOR C(27) XOR C(26) XOR C(25);
    new_crc(14) := D(7) XOR D(6) XOR D(4) XOR D(3) XOR D(2) XOR C(6) XOR C(31) XOR C(30) XOR C(28) XOR C(27) XOR C(26);
    new_crc(15) := D(7) XOR D(5) XOR D(4) XOR D(3) XOR C(7) XOR C(31) XOR C(29) XOR C(28) XOR C(27);
    new_crc(16) := D(5) XOR D(4) XOR D(0) XOR C(8) XOR C(29) XOR C(28) XOR C(24);
    new_crc(17) := D(6) XOR D(5) XOR D(1) XOR C(9) XOR C(30) XOR C(29) XOR C(25);
    new_crc(18) := D(7) XOR D(6) XOR D(2) XOR C(31) XOR C(30) XOR C(26) XOR C(10);
    new_crc(19) := D(7) XOR D(3) XOR C(31) XOR C(27) XOR C(11);
    new_crc(20) := D(4) XOR C(28) XOR C(12);
    new_crc(21) := D(5) XOR C(29) XOR C(13);
    new_crc(22) := D(0) XOR C(24) XOR C(14);
    new_crc(23) := D(6) XOR D(1) XOR D(0) XOR C(30) XOR C(25) XOR C(24) XOR C(15);
    new_crc(24) := D(7) XOR D(2) XOR D(1) XOR C(31) XOR C(26) XOR C(25) XOR C(16);
    new_crc(25) := D(3) XOR D(2) XOR C(27) XOR C(26) XOR C(17);
    new_crc(26) := D(6) XOR D(4) XOR D(3) XOR D(0) XOR C(30) XOR C(28) XOR C(27) XOR C(24) XOR C(18);
    new_crc(27) := D(7) XOR D(5) XOR D(4) XOR D(1) XOR C(31) XOR C(29) XOR C(28) XOR C(25) XOR C(19);
    new_crc(28) := D(6) XOR D(5) XOR D(2) XOR C(30) XOR C(29) XOR C(26) XOR C(20);
    new_crc(29) := D(7) XOR D(6) XOR D(3) XOR C(31) XOR C(30) XOR C(27) XOR C(21);
    new_crc(30) := D(7) XOR D(4) XOR C(31) XOR C(28) XOR C(22);
    new_crc(31) := D(5) XOR C(29) XOR C(23);

    return new_crc;
    end COUNT_CRC;

    begin

    SELECT_STATE:process (CLK, RST)

    begin
    if (RST = '1') then
    STATE <= IDLE;
    CRC_BUF <= X"0000_0000";
    elsif (CLK'event and CLK = '1') then
    case STATE is
    when IDLE =>
    if (GENER_CRC = '1') then
    STATE <= RUN;
    CRC_BUF <= COUNT_CRC(TX_DATA, CRC_INIT_VALUE);
    else
    STATE <= IDLE;
    end if;
    when RUN =>
    if (GENER_CRC = '1') then
    STATE <= RUN;
    CRC_BUF <= COUNT_CRC (TX_DATA, CRC_BUF);
    else
    STATE <= STOP;
    end if;
    when STOP =>
    STATE <= IDLE;
    when others => null;
    end case;

    end if;

    end process;
    TXD(31) <= not CRC_BUF(31);
    TXD(30) <= not CRC_BUF(30);
    TXD(29) <= not CRC_BUF(29);
    TXD(28) <= not CRC_BUF(28);
    TXD(27) <= not CRC_BUF(27);
    TXD(26) <= not CRC_BUF(26);
    TXD(25) <= not CRC_BUF(25);
    TXD(24) <= not CRC_BUF(24);
    TXD(23) <= not CRC_BUF(23);
    TXD(22) <= not CRC_BUF(22);
    TXD(21) <= not CRC_BUF(21);
    TXD(20) <= not CRC_BUF(20);
    TXD(19) <= not CRC_BUF(19);
    TXD(18) <= not CRC_BUF(18);
    TXD(17) <= not CRC_BUF(17);
    TXD(16) <= not CRC_BUF(16);
    TXD(15) <= not CRC_BUF(15);
    TXD(14) <= not CRC_BUF(14);
    TXD(13) <= not CRC_BUF(13);
    TXD(12) <= not CRC_BUF(12);
    TXD(11) <= not CRC_BUF(11);
    TXD(10) <= not CRC_BUF(10);
    TXD(9) <= not CRC_BUF(9);
    TXD(8) <= not CRC_BUF(8);
    TXD(7) <= not CRC_BUF(7);
    TXD(6) <= not CRC_BUF(6);
    TXD(5) <= not CRC_BUF(5);
    TXD(4) <= not CRC_BUF(4);
    TXD(3) <= not CRC_BUF(3);
    TXD(2) <= not CRC_BUF(2);
    TXD(1) <= not CRC_BUF(1);
    TXD(0) <= not CRC_BUF(0);

    end crcgenerator_i8b_arch;


    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.std_logic_unsigned.all;

    entity crcgenerator_i8b_tb is
    end crcgenerator_i8b_tb;

    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.std_logic_unsigned.all;

    architecture rtl of crcgenerator_i8b_tb is
    SIGNAL clk: STD_LOGIC := '0'; -- Input clock
    SIGNAL rst: STD_LOGIC; -- Asynchronous active low reset
    SIGNAL GENER_CRC: STD_LOGIC; -- Assert to restart calculations
    SIGNAL TX_DATA: STD_LOGIC_VECTOR(7 downto 0); -- Input byte
    SIGNAL TXD: STD_LOGIC_VECTOR (31 downto 0); -- Output CRC
    component crcgenerator_i8b is
    Port (
    RST: in STD_LOGIC;
    CLK: in STD_LOGIC;
    GENER_CRC: in STD_LOGIC;
    TX_DATA: in STD_LOGIC_VECTOR (7 downto 0);
    TXD: out STD_LOGIC_VECTOR (31 downto 0)

    );
    end component;

    FOR U_0 : crcgenerator_i8b USE ENTITY work.crcgenerator_i8b;


    begin
    U_0 : crcgenerator_i8b
    PORT MAP (
    RST => RST,
    CLK => CLK,
    GENER_CRC => GENER_CRC,
    TX_DATA => TX_DATA,
    TXD => TXD
    );
    STIMULUS_CLK: CLK <= NOT CLK after 5 ns;
    STIMULUS_RST: RST <= '1', '0' after 20 ns;
    STIMULUS_newFrame: GENER_CRC <= '0', '1' after 25 ns;
    STIMULUS_inByte: TX_DATA <= X"00", X"11" after 25 ns, X"FF" after 35 ns,
    X"0F" after 45 ns, X"12" after 55 ns, X"34" after 65 ns,
    X"0F" after 75 ns, X"0F" after 85 ns, X"0F" after 95 ns;
    end;
     
    TomoP, Apr 14, 2009
    #10
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.