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.

VHDL code explaination for CRC

Status
Not open for further replies.

moottii

Full Member level 2
Full Member level 2
Joined
Feb 22, 2012
Messages
120
Helped
13
Reputation
26
Reaction score
13
Trophy points
1,298
Visit site
Activity points
1,962
Hi friends,
I have the VHDL code for CRC (ethernet 802.3), but I don't know how to use the code. For instance I don't know when I must set the "crc_en".
Could you please guide me?
(The code is belong to http://outputlogic.com/)
Thanks in advance

Code:
library ieee; 
use ieee.std_logic_1164.all;

entity crc_tx is 
  port ( data_in : in std_logic_vector (3 downto 0);
    crc_en , rst, clk : in std_logic;
    crc_out : out std_logic_vector (3 downto 0));
end crc_tx;

architecture imp_crc of crc_tx is	
  signal lfsr_q: std_logic_vector (31 downto 0);	
  signal lfsr_c: std_logic_vector (31 downto 0);	
begin	
    crc_out <= lfsr_q(31) & lfsr_q(30) & lfsr_q(29) & lfsr_q(28);

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


    process (clk,rst) begin 
      if (rst = '1') then 
        lfsr_q <= (others=>'1');
      elsif (clk'EVENT and clk = '1') then 
        if (crc_en = '1') then 
          lfsr_q <= lfsr_c; 
		  else
			 lfsr_q <= lfsr_q(27 downto 0) & X"F";
        end if; 
      end if; 
    end process; 
end architecture imp_crc;
 

Thank you dear friend. But this is about the way that "Parallel CRC" works. Interesting... serjik (the guy in the comments) has my problem :))
 

"Interesting... serjik (the guy in the comments) has my problem :))"

And as such expending search effort in that area may help find a solution. That be my hint to you good sir. ;)
 

I wanna complete this thread with the answer. I used the code of http://outputlogic.com/ for Ethernet (802.3) with 4-bits input data width. There are some points to get the correct result.
1. You have to reverse your input nibble(e.g., "1011" -> "1101")
2. You have to xor and reverse the final result (crc_out in this code). (e.g., crc_out(31 downto 0) -> not(crc_out(0 to 31))
 

I assume that you know that CRC has a magic initial word that you need to provide at the start of the message? This is the moment that you enable the CRC ...

here is how I did it. NextChecksum is a function very similar to yours.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
p_CkecksumProcessing : process (pi_ByteClk, pi_aRst, ChecksumRst)
      variable v_NextCRC32 : std_logic_vector (31 downto 0);
   begin
      if (pi_aRst = c_RstActive) or ChecksumRst then 
--         FromChecksum <= (others => '0');
         Checksum <= x"FF_FF_FF_FF";
      elsif rising_edge(pi_ByteClk) then
--         if Valid = '1' then
            if (ReleaseChecksum) then
--               FromChecksum <= pi_InterfaceFromSerDes.Data;
               v_NextCRC32 := NextChecksum(pi_InterfaceFromSerDes.Data, Checksum);
               Checksum <= v_NextCRC32;
            end if;
--         end if;
      end if;
   end process p_CkecksumProcessing;

 
Last edited:

I assume that you know that CRC has a magic initial word that you need to provide at the start of the message?

You initialize your register with "FFFFFFFF" and that's correct. As here : http://outputlogic.com/?p=158&cpage=1#comments
mentions : "The reason CRC LFSR is usually initialized with ‘1’s is to prevent the situation when all-zero data, or a long stream of leading zeros will cause the LFSR value not to change (we do want it to change for every data bit)"

This is the moment that you enable the CRC ...
Do you mean as soon as we initialize the register, the process of calculating begins?
In my code, there is a "crc_en" (crc enable) for enabling calculation.
 

I'll add some more code. You enable your crc checker as soon as you want to start using it. In my case, I want to transmit video and other data over a serial link. Between the data (video and processor data) there are gaps (idle condition), where the serial link goes to an idle state. a header is placed in front of the data and the crc is added at the end. All this is achieved in the main state machine. The same states are used to drive the CRC checker. This code is added here.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
p_FSM_Output : process (pi_SysClk, pi_aRst) is
   begin
      if pi_aRst = c_RstActive then
         ReleaseChecksum <= false;
         SerdesInDataEn <= false;
      elsif rising_edge(pi_SysClk) then
        if ByteTick then
         case IncomingFSM_State is
            when e_Init          =>
               ReleaseChecksum <= false;
               SerdesInDataEn <= false;
            when e_Idle          =>
               ReleaseChecksum <= false;
               SerdesInDataEn <= false;
            when e_Video_Prep    =>
               ReleaseChecksum <= true;
               SerdesInDataEn <= true;
            when e_Sync_Prep     =>
               ReleaseChecksum <= true;
               SerdesInDataEn <= true;
            when e_Fetch_Video   =>
               if ReadCounter > 0 then
                  ReleaseChecksum <= true;
               else
                  ReleaseChecksum <= false;
               end if;
               SerdesInDataEn <= true;
            when e_Fetch_CRC     =>
               ReleaseChecksum <= false;
               if FSM_Counter < 3 then
                  SerdesInDataEn <= true;
               else
                  SerdesInDataEn <= false;
               end if;
            when e_Fetch_uBlaze  =>
               ReleaseChecksum <= true;
               SerdesInDataEn <= true;
            when others          =>
               ReleaseChecksum <= false;
               SerdesInDataEn <= false;
         end case;
        end if;
      end if;
   end process p_FSM_Output;

 

Dear lucbra,
I don't understand what you say... My CRC is belong to ethernet 802.3 while your bus is serial. Can you explain what you are saying exactly?
Do you want to ask me some thing or you are just explaining your code for other users?
Thanks
 

the serialization is behind the crc generation. I just provided you an example implementation of CRC and how to append to a stream of data. The only difference with your application is that I have implemented the CRC generation as a function.

You should be able to build your application now as it is very similar.
 

Do you mean as soon as we initialize the register, the process of calculating begins?
In my code, there is a "crc_en" (crc enable) for enabling calculation.
A discussion of this code should consider it's specific operation, 4-Bit wide serial in- and output, apparently designed for ethernet with 4-Bit datapath.

The operation of crc_en seems quite obvious.

It must be asserted while the input data for CRC calculation is present. It's deasserted after the last data nibble. The calculated CRC is then shifted during the next 8 nibbles, the CRC register is initialized to all '1' at the same time.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top