Forum: FPGA, VHDL & Co. DCF77-Signal Synchronisation


von Olaf S. (olaf_s_ber)


Lesenswert?

Guten Tag,
mit dem anschließenden Code, möchte ich eine Synchronisation mit dem 
DCF77-Signal erreichen. Zu den Prinzipien der Erkennung
und der Dekodierung brauch ich keine Hilfe. Diese sind mir klar und 
sollte vor der Programmierung wohl überlegt sein.
Mein Problem richtet sich dabei in der Umsetzung mit VHDL.
Kurz zur Erläuterung. Ich habe zwei Prozesse wobei der erste Prozess 
einen Zähler mit einem sauberen 100Hz Takt bei einer
abgetasteten logischen Null hoch zählt und bei einer abgetasteten 
logischen Eins zurücksetzt.
Ist der Zählerwert über dem Wert 179 (entspricht 1,79 s) wird eine 
Synchronisation erwartet (das DCF77 Signal ist bei Synchronisation 
mindestens 1,8 s logisch null) .
Über ein Flag-Signal sec_59 wird nun der zweite Prozess freigeschaltet, 
der auf eine steigende Flanke des DCF77 Signals wartet.
Dann wurde eine Synchronisation gefunden (Störungen bitte zunächst 
unbeachtet lassen).
Nun die alte Leier: die Simulationen funktionieren, die Realität sieht 
aber so aus:
Erste Synchronisation wird erkannt, darauffolgende Synchronisation aber 
nicht, danach folgt wieder eine Synchronisation und anschließend wieder 
nicht.
Leider sehe ich in der logischen Beschreibung keine Hinweise auf diesen 
reproduzierbaren Fehler und ich vermute eher, das es an meiner 
Programmierweise liegt, da ich in VHDL noch wenig erfahren bin.
Vielleicht erkennt jemand absolute "NoGos" in dem Code oder mögliche 
Fehlerfälle.
Ein Kommilitone meinte, ich solle das nicht so mit zwei Prozessen machen 
und lieber eine Statemachine programmieren.
Vielen Dank für die mögliche Hilfe.
Olaf
1
------------------------------------------------------------------------
2
library ieee;
3
use ieee.std_logic_1164.all;
4
use ieee.std_logic_arith.all;
5
6
entity sync is
7
8
  generic
9
  (
10
    MIN_COUNT:natural:=0;
11
    MAX_COUNT:natural:=179
12
    
13
    );
14
  
15
  port
16
  (   
17
    reset         :in std_logic;
18
    clk100Hz      :in std_logic;
19
    DCF77         :in std_logic;
20
    sync          :out std_logic := '0'
21
    
22
    );
23
    
24
end entity;
25
architecture rtl of sync is
26
  
27
  signal sec_59               : boolean := false;
28
  signal sec_59_release       : boolean := false;
29
  
30
begin
31
  process (reset,clk100Hz,DCF77,sec_59_release)
32
    variable cnt : integer range MIN_COUNT to MAX_COUNT;
33
  begin  
34
  if (reset = '1') then  
35
    if rising_edge(clk100Hz) then
36
      if(DCF77 ='0') then
37
        if (sec_59_release) then
38
          sec_59 <= false;
39
        end if;
40
        cnt := cnt+1;
41
        If(cnt > MAX_COUNT-1) then
42
          sec_59 <= true;
43
          cnt := 0;
44
        end if;
45
      else
46
        cnt := 0;
47
      end if;
48
    end if;
49
  else
50
    sec_59 <= false;
51
    cnt := 0;
52
  end if;
53
  end process;
54
  
55
  process (reset,DCF77,sec_59)
56
  begin  
57
  if (reset = '1') then      
58
    if (rising_edge(DCF77)) then
59
      if (sec_59) then
60
        sec_59_release <= true;
61
        sync <= '1';
62
      else
63
        sec_59_release <= false;
64
        sync <= '0';
65
      end if;
66
    end if;
67
  else
68
    sec_59_release <= false;
69
    sync <= '0';
70
  end if;
71
  end process;
72
  
73
end rtl;
74
------------------------------------------------------------------------

: Bearbeitet durch Moderator
von Jürgen S. (jurs)


Lesenswert?

Olaf Schulz schrieb:
> Ist der Zählerwert über dem Wert 179 (entspricht 1,79 s) wird eine
> Synchronisation erwartet (das DCF77 Signal ist bei Synchronisation
> mindestens 1,8 s logisch null) .
...
> Erste Synchronisation wird erkannt, darauffolgende Synchronisation aber
> nicht, danach folgt wieder eine Synchronisation und anschließend wieder
> nicht.
> Leider sehe ich in der logischen Beschreibung keine Hinweise auf diesen
> reproduzierbaren Fehler und ich vermute eher, das es an meiner
> Programmierweise liegt, da ich in VHDL noch wenig erfahren bin.

Ich kenne zwar null von Deinem VHDL, aber grau ist alle Theorie.
Und Du verläßt Dich offenbar zu sehr auf die Theorie.

Und vernachlässigst das praktische Zeitverhalten von realen DCF-Modulen.

Reale DCF-Module geben nämlich nicht immer Impulse von der theoretisch 
zu erwartenden Impulsdauer (0,1 bzw. 0,2s) ab, sondern oftmals auch 
etwas längere Impulse.

So dauern dann beispielsweise die theoretisch 100ms langen Impulse am 
DCF-Modul dann z.B. 120 bis 130 ms und die theoretisch 200ms langen 
Impulse beispielsweise 220 bis 230 ms.

Demzufolge wäre z.B. wenn der letzte gesendete Impuls ein 230 ms langer 
Impuls ist die Pause bis zum nächsten Impuls nicht "mindestens 1,8 s 
logisch null" sondern nur 1,77 s lang.

Und mit so einem DCF-Modul angeschlossen greift Dein Code mit:
MAX_COUNT:natural:=179
natürlich immer dann voll ins Klo, wenn die letzte Absenkung in der 
Minute kein 100ms-Impuls sondern ein 200ms Impuls ist, der praktisch 
aber 230 ms lang ist und demzufolge nur zu 1,77s Absenkung führt und 
nicht zu 1,79s.

Versuch's vielleicht mal mit:
MAX_COUNT:natural:=170
und teste einfach auf mindestens 1,7s ohne einen gesendeten Impuls!

von Duke Scarring (Gast)


Lesenswert?

Du verwendest zwei Takte (clk100Hz, DCF77). Das schreit nach 
Clock-Domain-Crossing.
Ich würde den Code ändern, so das er mit dem schnellsten Takt läuft. Auf 
den langsameren Signalen wird dann eine Flankenerkennung gemacht.

Duke

von Olaf S. (olaf_s_ber)


Lesenswert?

Hallo Jürgen,
gerade Duschen und fast am Verzweifeln, danke für deine Antwort. Das 
klingt in sich schlüssig, so mal bei den Tests das letzte Bit immer eine 
Eins war und sich nicht geändert hat (Parität Datum). Ich habe zwar eine 
"Schutzzeit" eingebaut, da die 100Hz clk ja asynchron zum DCF77 Signal 
läuft (in dem Fall: 179-1 zu den 180 also 2 => 20ms).
Ich werde dass ausprobieren und dann berichten. Man sollte die Realität 
stets mit dem Oszi abbilden und weniger mit dem Kopf...
Dank für Deine schnelle Antwort.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Olaf Schulz schrieb:
> process (reset,clk100Hz,DCF77,sec_59_release)
> process (reset,DCF77,sec_59)
Arg viel Zeug in diesen Sensitivlisten...

> if (rising_edge(DCF77)) then
Das ist kein Takt, sondern nur ein Signal, das 1. einsynchronisiert und 
dann 2. auf eine Flanke untersucht werden muss.

Kurz: wenn ein Anfänger mehr als 1 Signal bei rising_edge() oder 
falling_edge() oder bei 'event hat, dann wird er früher oder später 
diese Erfahrung machen:
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren

Wenn du darüber nachgedacht hast, dann darfst du dir das mal genauer 
ansehen:
http://www.lothar-miller.de/s9y/categories/56-DCF77  ;-)

> Ein Kommilitone meinte, ich solle das nicht so mit zwei Prozessen machen
> und lieber eine Statemachine programmieren.
Auch knapp vorbei...
Wobei du natürlich auch schon eine FSM in deinem Design hast, denn jeder 
Zähler ist schon ein Zustandsautomat, wenn auch ein einfacher...

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.