Alex Baumer schrieb:
> für ein Projekt in meinem Studium soll ich ein DCF77-Signal auswerten.
Das allein wäre ja nun eine eher flache Aufgabe, die in einem halben Tag
erledigt wäre:
http://www.lothar-miller.de/s9y/archives/77-DCF77-Decoder.html
> Wie gehe ich beim Entwicklen von digitalen Filtern vor? Bzw. wie kann
> ich eine "intelligente" eindeutige Erkennung der Signallängen von
> logisch 1 bzw. logisch 0 in VHDL umsetzen?
Da wirds dann interessanter und man darf sich hier ruhig mal Anregungen
aus der Mikrocontrollerecke holen. Dort wird eine Flanke erst bei
oftmaligem stabilem Abtasten eines Pegels für gültig erklärt. Damit wäre
dieser Ansatz geeigneter:
1 | library IEEE;
|
2 | use IEEE.STD_LOGIC_1164.ALL;
|
3 | use IEEE.NUMERIC_STD.ALL;
|
4 |
|
5 | entity DCF77 is
|
6 | Generic( fclk : integer := 50000000 ); -- 50MHz
|
7 | -- Generic( fclk : integer := 50000 ); -- 50kHz
|
8 | Port ( clk : in std_logic;
|
9 | dcf : in std_logic;
|
10 | dcf_sec0 : out std_logic;
|
11 | bitsout : out std_logic_vector (58 downto 0) );
|
12 | end DCF77;
|
13 |
|
14 | architecture Behavioral of DCF77 is
|
15 | constant t10ms : integer := (fclk/100)-1; -- 10 ms
|
16 | signal cnt10ms : integer range 0 to t10ms := 0; -- Vorteiler 10 ms
|
17 | signal cnt : integer range 0 to 110 := 0; -- Zähler bis 110*10ms = 1.1 sec
|
18 | signal dcfsr : std_logic_vector(3 downto 0);
|
19 | signal dcfakt : std_logic := '0';
|
20 | signal dcfold : std_logic := '0';
|
21 | signal bits : std_logic_vector(58 downto 0):= (others=>'0');
|
22 | begin
|
23 | process begin
|
24 | wait until rising_edge(clk);
|
25 | if (cnt10ms < t10ms) then
|
26 | cnt10ms <= cnt10ms+1;
|
27 | else -- 10ms vorbei
|
28 | cnt10ms <= 0;
|
29 | -- Einsynchronisieren und Störpeaks ausfiltern:
|
30 | -- nur wenn 3x der selbe Pegel abgetastet wurde, ist er gültig
|
31 | dcfsr <= dcfsr(2 downto 0) & dcf;
|
32 | dcfold <= dcfakt;
|
33 | if (dcfsr(3 downto 1)="111") then dcfakt <= '1'; end if;
|
34 | if (dcfsr(3 downto 1)="000") then dcfakt <= '0'; end if;
|
35 |
|
36 | -- Zaehler hochzählen (sättigend bei 1.1 sec)
|
37 | if (cnt < 110) then cnt <= cnt+1; end if;
|
38 |
|
39 | -- steigende Flanke vom DCF-Signal
|
40 | dcf_sec0 <= '0'; -- für 1 Taktzyklus bei Sekunde 0 aktiv
|
41 | if (dcfakt='1' and dcfold='0') then
|
42 | if (cnt = 110) then -- Überlauf? ja: Sekunde 59 war da
|
43 | dcf_sec0 <= '1'; -- Sekunde 0 anzeigen
|
44 | bitsout <= bits; -- die gesammelten Daten übergeben
|
45 | bits <= (others=>'0'); -- Bit-Schiebegregister zuruecksetzen
|
46 | end if;
|
47 | cnt <= 0;
|
48 | end if;
|
49 |
|
50 | -- einlesen bei fallender Flanke vom DCF-Signal
|
51 | if (dcfakt='0' and dcfold='1') then
|
52 | if (cnt < 15) then -- Grenze 150ms
|
53 | bits <= '0' & bits(58 downto 1); -- kurzer Impuls: 0 von links einschieben
|
54 | else
|
55 | bits <= '1' & bits(58 downto 1); -- langer Impuls: 1 von links einschieben
|
56 | end if;
|
57 | end if;
|
58 |
|
59 | end if;
|
60 | end process;
|
61 | end Behavioral;
|
Das "Filtern" ist also nur eine Plausibilitätskontrolle über 30ms:
solange darf kein anderer Pegel auftreten, dann wird der eingetastete
Pegel als gültig erkannt und für die weitere Verarbeitung genommen.
Eine weitere "Filterfunktion" steckt in der Abfrage der Dauer eines
High-Pegels. Ist der High-Pegel irgendwas zwischen 30ms und 140ms, dann
wird eine '0' erkannt, ab 150ms wird das Bit als '1' erkannt.
Dazu kommt dann noch die Plausibilitätskontrolle mit den erwähnten
Paritybits für die einzenlen Stellen.
Und zu guter Letzt wäre es noch sinnvoll, die gerade empfangene Minute
mit der vorhergehenden auf eklatante Unterschiede zu vergleichen und nur
bei einer plausiblen Abweichung die erkannte Zeit für gültig zu
erklären.
Insgesamt müssen also einige "Filtermaßnahmen" auf die einzelnen Ebenen
angewendet werden, bevor ein Telegramm für gültig erklärt werden kann.