Ein DCF-Signal besteht aus Impulsfolgen, die pro Sekunde mit unterschiedlich langen High-Pegeln eine 0 (=100ms high) bzw. eine 1 (=200ms high) codieren. Die 59. Sekunde wird zur Synchronisation verwendet und wird mit low-Pegel ausgegeben. Die steigende Flanke nach der 58. skeunde ist daher dann die Sekunde 0.
Die Auswertung des DCF-Signals wird also von einem Zähler übernommen, der mit einer steigenden Flanke zurückgesetzt wird. Bei einer fallenden Flanke wird dann entsprechend dem Zählerstand eine '0' (<150ms) oder eine '1' (>150ms) übernommen.
Alternativ kann auch beim Zählerstand 150ms einfach der Pegel des DCF-Signals eingelesen werden.
Erreicht der Zähler einen Wert größer 1 Sekunde, war das die 59. Sekunde. Bei der der nächsten steigenden Flanke des DCF-Signals werden dann die eingelesenen Bits zur weiteren Verarbeitung über ein Pufferregister bereitgestellt.
In dem folgenden Code sollte vor der Synthese eine der beiden Varianten (beide funktionieren gleich gut) der Bit-Auswertung auskommentiert werden
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DCF77 is
Generic( fclk : integer := 50000000 ); -- 50MHz
Port ( clk : in std_logic;
dcf : in std_logic;
dcf_sec0 : out std_logic;
bitsout : out std_logic_vector (58 downto 0) );
end DCF77;
architecture Behavioral of DCF77 is
constant cntmax : integer := (11*fclk)/10; -- 1.1 sec
constant cntsample : integer := (15*fclk)/100; -- 150 ms
signal cnt : integer range 0 to cntmax := 0; -- Zähler bis 1.1 sec
signal dcfsr : std_logic_vector(2 downto 0);
signal bits : std_logic_vector(58 downto 0):= (others=>'0');
begin
process begin
wait until rising_edge(clk);
-- Einsynchronisieren
dcfsr <= dcfsr(1 downto 0) & dcf;
-- erst Zaehler hochzählen (sättigend bei 1.1 sec)
if (cnt < cntmax) then
cnt <= cnt+1;
end if;
-- steigende Flanke vom DCF-Signal
dcf_sec0 <= '0'; -- für 1 Taktzyklus bei Sekunde 0 aktiv
if (dcfsr(2 downto 1)="01") then
if (cnt = cntmax) then -- Überlauf? ja: Sekunde 59 war da
dcf_sec0 <= '1'; -- Sekunde 0 anzeigen
bitsout <= bits; -- die gesammelten Daten übergeben
bits <= (others=>'0'); -- Bit-Schiebegregister zuruecksetzen
end if;
cnt <= 0;
end if;
-- Variante 1: einlesen bei fallender Flanke vom DCF-Signal
if (dcfsr(2 downto 1)="10") then
if (cnt < cntsample) then -- kurzer Impuls? Grenze 150ms
bits <= '0' & bits(58 downto 1); -- ja: 0 von links einschieben
else
bits <= '1' & bits(58 downto 1); -- nein: 1 von links einschieben
end if;
end if;
-- --> Ressourcenverbrauch
-- Number of Slices 88
-- Number of Slice FFs 137
-- Number of 4 input LUTs 104
-- Variante 2: bei Zeitpunkt "150ms" einlesen
if (cnt = cntsample) then -- DCF-Signal einlesen bei 150ms
bits <= dcfsr(2) & bits(58 downto 1);
end if;
-- --> Ressourcenverbrauch
-- Number of Slices 87
-- Number of Slice FFs 137
-- Number of 4 input LUTs 103
end process;
end Behavioral;
Zusammen mit der Testbench unten ergeben sich folgende Waveforms:
Hier der DCF77-Decoder incl. Testbench zum Download: DCF77.zip
Mit diesem Decoder werden nur die rohen Daten bereitgestellt. In dem Modul darüber muß dann noch die gesamte Plausibilitätskontrolle (Parity), die Validierung und die weitere Verwaltung der empfangenen Daten realisiert werden.