Forum: FPGA, VHDL & Co. CRC-Berechnung - Benötige Hilfe bei der Fehlerfindung


von Martin (Firma: Angestellt) (herki)


Lesenswert?

Hallo Liebe Mikrocontroller.net-Leser

Ich schreibe im Moment für einen CPLD eine SPI-GPIO-Erweiterung.
Da die Daten die über den SPI-Bus übertragen werden sehr wichtig sind 
wird eine CRC Checksumme über die gesendeten Daten gebildet und 
ebenfalls über den SPI-Bus übertragen.
Das Format der Übertragung sieht folgendermaßen aus:
Telegramm 1
Checksumme über Telegramm 1
Telegramm 2
Checksumme über Telegramm 2

Da der Mikrocontroller (Master) lediglich ein 8 Bit breiten TX-Buffer 
für das SPI-Modul besitzt ist die Aufteilung in 4 Übertragungen a 8 Bit 
notwendig.

Ich habe als Generatorpolynom folgendes ausgewählt:
x^8+x^4+x^3+x^2+1 (==> somit ist die Checksumme ebenfalls 8 Bit breit)

Ich habe mir das ganze mal manuell durchgerechnet. Als verwendetes 
Testdatenmuster habe ich 0xA3 (0b10100011) verwendet:

1010 0011 0000 0000 : 1 0001 1101
1000 1110 1
0010 1101 100
  10 0011 101
  00 1110 0010 0
     1000 1110 1
     0110 1100 10
      100 0111 01
      010 1011 110
       10 0011 101
       00 1000 0110

Somit habe ich als Rest 0x86.
Auf der Seite http://zorc.breitbandkatze.de/crc.html habe ich das ganze 
verifizieren wollen.
Da komme ich aber auf folgende Werte:
Eingestellte Parameter: CRC-Order: 8  /  CRC-Polynom: 1D  /  Initialwert 
FF  /  Final XOR value:00    Reverse Data Bytes 0    Final XOR value 0
Result: 8A

Eingestellte Parameter: CRC-Order: 8  /  CRC-Polynom: 1D  /  Initialwert 
FF  /  Final XOR value:00    Reverse Data Bytes 0    Final XOR value 1
Result: 51

Eingestellte Parameter: CRC-Order: 8  /  CRC-Polynom: 1D  /  Initialwert 
FF  /  Final XOR value:00    Reverse Data Bytes 1    Final XOR value 0
Result: B9

Eingestellte Parameter: CRC-Order: 8  /  CRC-Polynom: 1D  /  Initialwert 
FF  /  Final XOR value:00    Reverse Data Bytes 1    Final XOR value 1
Result: 9D

Meine Testbench liefert mir als Ergebnis 0x42.


Als Testbench habe ich folgenden Code:
1
                                       -- Testbench
2
 
3
library ieee;
4
use ieee.std_logic_1164.all;
5
use ieee.std_logic_arith.all;
6
use ieee.std_logic_unsigned.all;
7
use ieee.numeric_std.all;
8
9
10
-- Leere entity
11
entity mein_DUT_tb is
12
generic (
13
    gDatenlaenge  : integer :=8;
14
  gCRCLaenge    : integer :=8);
15
16
end entity mein_DUT_tb ;
17
 
18
architecture Verhalten of mein_DUT_tb is
19
20
 -- Moduldeklaration
21
COMPONENT  crc 
22
port (
23
  data_in  : in std_logic_vector (gDatenlaenge - 1 downto 0);
24
    crc_en   : in std_logic;
25
  rst    : in std_logic;
26
  clk    : in std_logic;
27
    crc_out : out std_logic_vector (gCRCLaenge - 1 downto 0));
28
end component;
29
30
signal    data_in  :  std_logic_vector (gDatenlaenge - 1 downto 0):= (others =>'0');  
31
signal    crc_en   :  std_logic  :='0';
32
signal    rst    :  std_logic  :='0';
33
signal    clk    :  std_logic  :='0';
34
signal    crc_out  :  std_logic_vector (gCRCLaenge - 1 downto 0):= (others =>'0');  
35
36
procedure Testdaten_anlegen 
37
(
38
signal crc_en  : out  std_logic;
39
signal rst    : out  std_logic
40
) is
41
  
42
begin
43
  --wait until rising_edge(clk);
44
  crc_en<= '1';
45
  wait until rising_edge(clk);
46
  wait until rising_edge(clk);
47
  crc_en<= '0';
48
  rst<='1';
49
  wait until rising_edge(clk);
50
  rst<='0';
51
  wait until rising_edge(clk);
52
  
53
end Testdaten_anlegen ;
54
--0000010110001100
55
56
57
begin
58
  clk   <= not clk  after 20 ns;  -- 25 MHz Taktfrequenz
59
  
60
61
  
62
63
  
64
 CRC_berechnen: process 
65
  begin  
66
      rst <= '1';
67
    wait until rising_edge(clk);
68
      rst <= '0';
69
    wait until rising_edge(clk);
70
  
71
    
72
  data_in <= conv_std_logic_vector((163),gDatenlaenge);  Testdaten_anlegen (crc_en => crc_en, rst => rst);  
73
  
74
75
  for I in 0 to 255 loop
76
    data_in <= conv_std_logic_vector((I),gDatenlaenge);  Testdaten_anlegen (crc_en => crc_en, rst => rst);
77
    end loop;
78
    
79
 wait until rising_edge(clk);
80
  crc_en<= '1';
81
  wait until rising_edge(clk);
82
  crc_en<= '0';
83
  wait until rising_edge(clk);
84
 
85
  
86
  
87
end process;
88
89
 
90
  -- Modulinstatziierung
91
  mein_dut : crc
92
  port map (
93
   data_in    =>    data_in,
94
  crc_en     =>    crc_en,
95
  rst      =>    rst,
96
  clk      =>    clk,
97
  crc_out    =>    crc_out            
98
  );
99
         
100
end architecture;

Als DUT habe ich folgenden generierten Code von 
http://outputlogic.com/?page_id=321 eingefügt
1
-------------------------------------------------------------------------------
2
-- Link zum Generieren des Files: http://outputlogic.com/?page_id=321
3
-------------------------------------------------------------------------------
4
-------------------------------------------------------------------------------
5
-- Ports
6
-- data_in    : Paralleler Eingang der Daten
7
-- crc_en    : Startsignal
8
-- rst      : Reset
9
-- clk      : CLK-Signal
10
-- crc_out    : Paralleler Ausgang an dem die berechnete CRC bereitgestellt wird
11
12
13
-------------------------------------------------------------------------------
14
-- Copyright (C) 2009 OutputLogic.com
15
-- This source file may be used and distributed without restriction
16
-- provided that this copyright statement is not removed from the file
17
-- and that any derivative work contains the original copyright notice
18
-- and the associated disclaimer.
19
-- 
20
-- THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
21
-- OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
22
-- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23
-------------------------------------------------------------------------------
24
-- CRC module for data(7:0)
25
--   lfsr(7:0)=1+x^2+x^3+x^4+x^8;
26
-------------------------------------------------------------------------------
27
library ieee;
28
use ieee.std_logic_1164.all;
29
30
entity crc is
31
  port ( data_in : in std_logic_vector (7 downto 0);
32
    crc_en , rst, clk : in std_logic;
33
    crc_out : out std_logic_vector (7 downto 0));
34
end crc;
35
36
architecture imp_crc of crc is
37
  signal lfsr_q: std_logic_vector (7 downto 0);
38
  signal lfsr_c: std_logic_vector (7 downto 0);
39
begin
40
    crc_out <= lfsr_q;
41
42
    lfsr_c(0) <= lfsr_q(0) xor lfsr_q(4) xor lfsr_q(5) xor lfsr_q(6) xor data_in(0) xor data_in(4) xor data_in(5) xor data_in(6);
43
    lfsr_c(1) <= lfsr_q(1) xor lfsr_q(5) xor lfsr_q(6) xor lfsr_q(7) xor data_in(1) xor data_in(5) xor data_in(6) xor data_in(7);
44
    lfsr_c(2) <= lfsr_q(0) xor lfsr_q(2) xor lfsr_q(4) xor lfsr_q(5) xor lfsr_q(7) xor data_in(0) xor data_in(2) xor data_in(4) xor data_in(5) xor data_in(7);
45
    lfsr_c(3) <= lfsr_q(0) xor lfsr_q(1) xor lfsr_q(3) xor lfsr_q(4) xor data_in(0) xor data_in(1) xor data_in(3) xor data_in(4);
46
    lfsr_c(4) <= lfsr_q(0) xor lfsr_q(1) xor lfsr_q(2) xor lfsr_q(6) xor data_in(0) xor data_in(1) xor data_in(2) xor data_in(6);
47
    lfsr_c(5) <= lfsr_q(1) xor lfsr_q(2) xor lfsr_q(3) xor lfsr_q(7) xor data_in(1) xor data_in(2) xor data_in(3) xor data_in(7);
48
    lfsr_c(6) <= lfsr_q(2) xor lfsr_q(3) xor lfsr_q(4) xor data_in(2) xor data_in(3) xor data_in(4);
49
    lfsr_c(7) <= lfsr_q(3) xor lfsr_q(4) xor lfsr_q(5) xor data_in(3) xor data_in(4) xor data_in(5);
50
51
52
    process (clk,rst) begin
53
      if (rst = '1') then
54
        lfsr_q <= b"11111111";
55
      elsif (clk'EVENT and clk = '1') then
56
        if (crc_en = '1') then
57
          lfsr_q <= lfsr_c;
58
        end if;
59
      end if;
60
    end process;
61
end architecture imp_crc;


Wenn mir da vielleicht jemand einen Tipp geben kann wo der Fehler liegt 
wäre ich sehr dankbar.

Viele Grüße

Martin

von Martin (Firma: Angestellt) (herki)


Lesenswert?

Guten Morgen

Hat keiner eine Idee?

VG

Martin

von Johann (Gast)


Lesenswert?

Die Leute müssen erst wach werden ^^

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

>
>     process (clk,rst) begin
>       if (rst = '1') then
>         lfsr_q <= b"11111111";
>       elsif (clk'EVENT and clk = '1') then
>         if (crc_en = '1') then
>           lfsr_q <= lfsr_c;
>         end if;
>       end if;
>     end process;
> end architecture imp_crc;
>
> [/vhdl]
>

Das CRC Thema ist sehr groß.
CRC beschreibt den Vorgang. Unterschiede gibt es noch in den Startwerten 
und wie der CRC Wert übertragen wird.

Ich habe mich mit CRC32 für Ethernet beschäftigt. hier wird der CRCWert 
negiert übertragen.
Der Startzustand der Register sind 1.
Das ist bereits die Erste mathematische Optimierung. Dadurch werden die 
ersten einlaufend Bits des Datenstromes negiert.
Für dein CRC muss du mehr wissen oder du kannst mit einem CRC-Generator 
kleine Datenström berechnen. Günstig ist hier ein Byte und die 
dazugehörige Checksumme.


Versuchen mal den Resetzustand auf ... zu ändern.

   lfsr_q <= b"00000000";

von Martin (Firma: Angestellt) (herki)


Lesenswert?

Hallo Rene

Vielen Dank für Deine Antwort.

Ich habe den Resetzustand wie Du vorgeschlagen hast geändert.
Resultat:
Die simulierten Ergebnisse entsprechen meiner manuellen Rechnung. :)

Leider komme ich bei der Berechnung mit dem CRC-Rechner 
(http://zorc.breitbandkatze.de/crc.html) aber auf andere Ergebnisse.

Hast Du mit dem Rechner Erfahrung?
Ich habe folgende Werte eingegeben:
Startwert 0
CRC-Order 8
CRC-Polynom 1D

Wenn mir da vielleicht noch jemand unter die Arme greifen kann wäre mein 
Tag gerettet.

Viele Grüße

Martin

von Elizar (Gast)


Lesenswert?


von Purzel H. (hacky)


Lesenswert?

Bei einem SPI verwendet man in der Regel keinen CRC, denn es kann ja 
keine Fehler geben. Es ist alles auf einer Leiterplatte, EMV Probleme 
hat man keine. Es gibt keine Kabel durch irgendwelche Umgebungen.
Falls man doch EMV Probleme hat sollte man die loesen. Nicht mit einem 
CRC, sondern mit einem richtigen Design. Und auf ein Kabel gehoert SPI 
auch nicht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.