Forum: FPGA, VHDL & Co. VHDL, DFC77, riesen Problem!


von voodoopuppe (Gast)


Lesenswert?

Hallo Leute,

folgendes Problem: Ich möchte gern ein DFC77-Signal in VHDL auswerten.
Wie ich das THEORETISCH mache, habe ich auch schon überlegt. Ich möchte 
von jeder fallenden Flanke aus anfangen und den Abstand zur nächsten 
steigenden Flanke messen (scheinbar funktioniert es nicht, von einer 
fallenden zu einer steigenden Flanke zu messen - wenn doch, dann bitte 
klärt mich auf - Quartus meint auf jeden Fall, es ginge nicht).

Jetzt hab ich mir folgenden Codefetzen überlegt:
1
    if(reset = '1') then
2
      timer_hh <= 0;
3
      sek_nr  <= 0;
4
      zustand  <= 0;
5
    end if;
6
    
7
    if(rising_edge(takt)) then
8
      timer_hh <= timer_hh+1;
9
    end if;
10
    if(falling_edge(dcf)) then
11
      -- hier beginnen wir mit dem zaehlen
12
      timer_hh <= 0;
13
    elsif(rising_edge(dcf)) then
14
      -- zaehler stoppen und Zeit auswerten
15
      if(timer_hh = 200) then
16
      -- jetzt haben wir eine 1 bekommen
17
        sek_nr <= sek_nr + 1;
18
      elsif(timer_hh = 100) then
19
      -- jetzt haben wir eine 0 bekommen
20
        sek_nr <= sek_nr + 1;
21
      elsif(timer_hh > 500) then
22
      -- jetzt sind wir synchron zur Minute
23
        sek_nr <= 0;
24
      end if;
25
    end if;

Dieser Code funktioniert problemlos (zumindest was das synthetisieren 
angeht).
1
    if(reset = '1') then
2
      timer_hh <= 0;
3
      sek_nr  <= 0;
4
      zustand  <= 0;
5
    end if;
6
    
7
    if(rising_edge(takt)) then
8
      timer_hh <= timer_hh+1;
9
    end if;
10
    if(falling_edge(dcf)) then
11
      -- hier beginnen wir mit dem zaehlen
12
      timer_hh <= 0;
13
    elsif(rising_edge(dcf)) then
14
      -- zaehler stoppen und Zeit auswerten
15
      if(timer_hh = 200) then
16
      -- jetzt haben wir eine 1 bekommen
17
        sek_nr <= sek_nr + 1;
18
      elsif(timer_hh = 100) then
19
      -- jetzt haben wir eine 0 bekommen
20
        sek_nr <= sek_nr + 1;
21
      elsif(timer_hh > 500) then
22
      -- jetzt sind wir synchron zur Minute
23
        sek_nr <= 0;
24
        sync <= '1';
25
      end if;
26
    end if;
Hier bekomme ich komischerweise den Fehler, dass "timer_hh" nicht 
außerhalb des "clock_edge" gelesen werden kann.
Der einzige Unterschied ist doch, dass ich jetzt den Ausgang SYNC mit 
einer 1 belege. Was genau hat jetzt der "timer_hh" damit zu tun?
Ich verstehe nicht, was genau da gerade passiert.
Kann mir das vielleicht jemand erklären?

von voodoopuppe (Gast)


Lesenswert?

Bevor ich es vergesse:
1
    if(timer_hh > 5) then
2
      sync <= '1';
3
    else
4
      sync <= '0';
5
    end if;
Hier kommt es zum gleichen Problem, sobald ich diesen Code UNTER den 
anderen, funktionierenden, schiebe.

Wie bekomme ich denn jetzt die Variable "timer_hh" nach "außen" (d.h. 
innerhalb des gleichen Blocks) ausgewertet?

Gesamter Quelltext:
1
--DCF77Block
2
3
4
library ieee;
5
use ieee.std_logic_1164.all;
6
use ieee.numeric_std.all;
7
use ieee.std_logic_arith.all;
8
9
10
entity dcf77 is
11
12
  port
13
  (
14
    dcf    : in   std_logic;
15
    takt    : in  std_logic;
16
    reset    : in   std_logic;
17
    sync    : out std_logic;
18
    sync_lvl  : out std_logic_vector(1 downto 0);
19
    out_min  : out std_logic_vector(5 downto 0);
20
    out_std  : out std_logic_vector(5 downto 0);
21
    out_tag  : out std_logic_vector(5 downto 0);
22
    out_mon  : out std_logic_vector(5 downto 0);
23
    out_jhr  : out std_logic_vector(5 downto 0)
24
  );
25
26
end entity;
27
28
-- Programmablauf:
29
-- warte auf fallende Flanke
30
-- 
31
32
33
architecture verhalten of dcf77 is
34
  signal zustand    : integer := 0;
35
  -- sek_nr bestimmt Position innerhalb der laufenden Minute
36
  signal sek_nr    : integer := 0;
37
  -- timer tiefhoch
38
  signal timer_hh  : integer := 0;
39
  signal temp      : integer := 0;
40
begin
41
  
42
  process (dcf, reset, takt)
43
  begin
44
    -- Zustand 0: Programmstart
45
    -- Zustand 1: Programm laeuft und hat erste fallende Flanke gefunden
46
    -- Zustand 2: Programm ist synchron
47
    if(reset = '1') then
48
      timer_hh <= 0;
49
      sek_nr  <= 0;
50
      zustand  <= 0;
51
    end if;
52
    
53
    if(rising_edge(takt)) then
54
      timer_hh <= timer_hh+1;
55
    end if;
56
    if(falling_edge(dcf)) then
57
      -- hier beginnen wir mit dem zaehlen
58
      timer_hh <= 0;
59
    elsif(rising_edge(dcf)) then
60
      -- zaehler stoppen und Zeit auswerten
61
      if(timer_hh = 200) then
62
      -- jetzt haben wir eine 1 bekommen
63
        sek_nr <= sek_nr + 1;
64
      elsif(timer_hh = 100) then
65
      -- jetzt haben wir eine 0 bekommen
66
        sek_nr <= sek_nr + 1;
67
      elsif(timer_hh > 500) then
68
      -- jetzt sind wir synchron zur Minute
69
        sek_nr <= 0;
70
      end if;
71
    end if;
72
    
73
    if(timer_hh > 5) then
74
      sync <= '1';
75
    else
76
      sync <= '0';
77
    end if;
78
    
79
  end process;
80
  
81
end verhalten;

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


Lesenswert?

voodoopuppe schrieb:
>    if(falling_edge(dcf)) then
>    :
>    elsif(rising_edge(dcf)) then

> Dieser Code funktioniert problemlos (zumindest was das synthetisieren
> angeht).
Das mußt du mir aber erst mal beweisen... :-/
Solche Bueteile die auf fallende und auf steigende Flanken reagieren 
gibt es in einem FPGA nicht.

> (scheinbar funktioniert es nicht, von einer fallenden zu einer
> steigenden Flanke zu messen - wenn doch, dann bitte
> klärt mich auf - Quartus meint auf jeden Fall, es ginge nicht).
Natürlich geht das. Aber ganz anders.

Lies mal dort meine Postulate und meditiere mal, welche du alle verletzt 
hast: Beitrag "vhdl-richtlinien f. synthese?"

voodoopuppe schrieb:
> Wie bekomme ich denn jetzt die Variable "timer_hh" nach "außen" (d.h.
> innerhalb des gleichen Blocks) ausgewertet?
Gar nicht.
Variablen sind nur innerhalb eines Prozesses sichtbar. Nach aussen 
verwendest du Signale. Ich brauche nur im seltensten Fall mal eine 
Variable. Warum brauchst du so viele?
Beitrag "Variable vs Signal"

Geh mal in dich und deinen ganzen Code nochmal durch...
Und wie gesagt: nur 1 Takt (der Quarz).
Und externe Signale einsynchronisieren (hier dein DCF-Signal).

von voodoopuppe (Gast)


Lesenswert?

Hallo,

danke erstmal für deine Antwort!

"Das mußt du mir aber erst mal beweisen... :-/
Solche Bueteile die auf fallende und auf steigende Flanken reagieren
gibt es in einem FPGA nicht."
Das habe ich mir schon fast gedacht - und genau das ist der Witz - der 
genannte Code funktioniert PROBLEMLOS. Sobald ich z.B. den sync-Ausgang 
belegen will, kommt der genannte Fehler. Das ist ja das verwirrende für 
mich an der ganzen Sache.

Ich muss sagen, ich bin selbst kein VHDL-Freak und ich mache das auch 
nur, weil ich das Fach für den Studienabschluss belegen "muss" (im 
Grunde nur um eine andere Note ggf. ausgleichen zu können). Ganz ehrlich 
bin ich kein Fan dieser Sprache - und hätte nicht gedacht, dass das 
Ganze so viele Probleme bereitet - hat es doch im Semester zuvor 
wunderbar geklappt, als wir eine normale Uhr (ohne Funk-Zusatz) 
programmiert haben.

So recht weiter bin ich nach dem ersten Lesen der Threads, bzw. der 
Anleitung zum Einsynchronisieren noch nicht.

Bezüglich des einsynchronisieres des externen Signals:
Vermutlich wird es auf ein "wait until rising_edge(dcf);" rauslaufen, 
welches ich dann irgendwie mit einem "dcfsig <= 1;" belegen werde, um es 
dann in einem anderen Prozess mittels
1
if(dcfsig = 1) then
2
--Zeitmessen;
3
dcfsig = 0;
4
end if;[VHDL]
5
auszuwerten und die Variable zurückzusetzen - oder wäre das vollkommen falsch? Dann bliebe im Grunde eben nur mehr das Problem mit dem Signal vom Takt.
6
7
Um es mal ein wenig codetechnisch darzustellen:
8
[vhdl]
9
process begin
10
  wait until rising_edge(dcf);
11
  dcfok <= 1;
12
end process;
13
14
process  begin
15
  wait until rising_edge(takt);
16
  timer_hh <= timer_hh+1;
17
end process;
18
19
process begin
20
  if(dcfok = 1)
21
    -- do sth
22
    timer_hh <= 0;
23
    dcfok <= 0;
24
  end if;
25
end process;
Jetzt mal ganz davon abgesehen, dass das so nicht funktioniert, weil ich 
wohl versuche mehrmals auf das gleiche Signal zuzugreifen (dcfok <= 0 
und timer_hh <= 0).
Ist das der richtige Weg, wie es aussehen sollte?

Mir fehlt leider ein wenig eine "konkretere" Hilfe. Natürlich kann ich 
mir jetzt auch ein Buch über VHDL zulegen oder das ganze Internet nach 
Tutorials durchforsten. Das hilft mir bei meinem Problem aber eher 
weniger.

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


Lesenswert?

voodoopuppe schrieb:
> Jetzt mal ganz davon abgesehen, dass das so nicht funktioniert, weil ich
> wohl versuche mehrmals auf das gleiche Signal zuzugreifen (dcfok <= 0
> und timer_hh <= 0).
Richtig, das gibt "Multiple Sources", weil von mehreren Prozessen (oder 
auch concurrent) auf das Selbe Signal geschrieben wird.

voodoopuppe schrieb:
> Vermutlich wird es auf ein "wait until rising_edge(dcf);" rauslaufen,
Nein. Das dcf ist ein stinknormales asynchrones externes Signal. Der 
einzige Takt, den du in deinem Design haben wirst, heißt (bei dir 
offenbar) takt und kommt vom Quarzoszillator im Bereich um 
20...100MHz. Ausschliesslich diese Buchstabenkombination wird bei 
rising_edge() stehen. Ein falling_edge() wirst du nicht haben.

Ich würde das Problem aufteilen:
1. Erkennen einer 0, 1 und des Sync-Bits (die lange 0)
2. Ein 60 Bit langes Schieberegister, das den Datenstrom aufnimmt
3. Einen Übergabeimpuls an die Stunden- und Minuten-Register.

Ich würde eine DCF-Uhr so aufbauen, dass die Uhr an sich erst mal läuft 
und nur ab und an, wenn das DCF-Signal gut ist, neu synchronisiert wird.

> hat es doch im Semester zuvor wunderbar geklappt, als wir eine
> normale Uhr (ohne Funk-Zusatz) programmiert haben.
Nur zur Info: wieviele Takte waren da drin?

von voodoopuppe (Gast)


Lesenswert?

Im Grunde hatten wir dort eben nur EINEN Takt - nämlich den Quarz mit 
seinen ~50Mhz (war ne etwas krumme MHz-Zahl, also nicht exakt 50).

Für die Schalter zum stellen der Uhr haben wir den weiter 
runtergebrochen - was aber im Grunde nichts daran geändert hat, dass wir 
in jedem Prozess/Entity nur auf EIN Signal prüfen mussten, welches er 
von außen bekommen hat.



Ich würde das Problem aufteilen:
1. Erkennen einer 0, 1 und des Sync-Bits (die lange 0)
2. Ein 60 Bit langes Schieberegister, das den Datenstrom aufnimmt
3. Einen Übergabeimpuls an die Stunden- und Minuten-Register.

So ähnlich haben wir uns das auch gedacht. Die Frage ist eben:
Wie messe ich, nachdem ich die ganzen Takte mit gezählt habe (muss ja 
wissen, wieviele ms vergangen sind seit der letzten Flanke), die Zeit 
zwischen 2 Flanken?

Theoretisch könnte man auch ohne Flanke arbeiten, indem man misst, wie 
lang das Signal auf "1" oder "0" war - im Sinne von (Pseudocode):
1
process  begin
2
  wait until rising_edge(takt);
3
  if(dcf = '1') then
4
    timer_hh <= timer_hh+1;
5
  end if;
6
end process;
7
8
process begin
9
  if(dcf = '0') then
10
    if(zustand = 1) then
11
      if(timer_hh = 900) then
12
        -- wir haben ne 0
13
      elsif(timer_hh = 800) then
14
        -- wir haben ne 1
15
      elsif(timer_hh > 1000) then
16
        -- wir haben ne neue Sekunde
17
      end if;
18
    timer_hh <= 0;
19
    zustand <= 0;
20
  end if;
21
  elsif(dcf = '1') then
22
    zustand <= 1;
23
  end if;
24
end process;

Damit könnte man vorerst scheinbar die Nullen und Einsen erkennen - und 
sich theoretisch wohl auch zum Signal synchronisieren (auf Grund der 
langen 0).
Aber ob das funktionieren wird, bzw. so gedacht ist wie du das meinst?

Damit würde ich nur auswerten ob das DCF-Signal 0 oder 1 ist.
Das Problem mit den Multiple Sources hätte ich allerdings ja auch in 
meinem neuen Beispiel. Dort schreibe ich einmal die timer_hh im ersten 
und einmal im zweiten Prozess. Natürlich könnte ich das jetzt abhängig 
von der Variable "zustand" machen, ob ich den Wert zurück auf 0 setze. 
Denn den Zustand setze ich ja erst dann auf 0, wenn ich alle benötigten 
Werte ausgelesen habe.
Soll heißen, ich hätte es jetzt so probiert:
1
process  begin
2
  wait until rising_edge(takt);
3
  if(dcf = '1') then
4
    timer_hh <= timer_hh+1;
5
  end if;
6
  if(zustand = 0) then
7
    timer_hh <= 0;
8
  end if;
9
end process;
10
11
process begin
12
  if(dcf = '0') then
13
    if(zustand = 1) then
14
      if(timer_hh = 900) then
15
        -- wir haben ne 0
16
      elsif(timer_hh = 800) then
17
        -- wir haben ne 1
18
      elsif(timer_hh > 1000) then
19
        -- wir haben ne neue Sekunde
20
      end if;
21
    zustand <= 0;
22
  end if;
23
  elsif(dcf = '1') then
24
    zustand <= 1;
25
  end if;
26
end process;

Somit schreibe ich die jeweiligen Variablen nur innerhalb EINES 
Prozesses.
Ob das jetzt aber 100% so klappt weiß ich nicht.
Was sagen die Profis? ;)

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


Lesenswert?

voodoopuppe schrieb:
> Im Grunde hatten wir dort eben nur EINEN Takt - nämlich den Quarz mit
> seinen ~50Mhz (war ne etwas krumme MHz-Zahl, also nicht exakt 50).
>
> Für die Schalter zum stellen der Uhr haben wir den weiter
> runtergebrochen - was aber im Grunde nichts daran geändert hat, dass wir
> in jedem Prozess/Entity nur auf EIN Signal prüfen mussten, welches er
> von außen bekommen hat.
Ein Takt ist das, was irgendwo bei rising_edge() oder falling_edge() 
in der Klammer oder vor 'event steht. Und dort hat immer die selbe 
ASCII-Zeichenkette zu stehen. Erst dann ist wirklich nur 1 Takt im 
System.

voodoopuppe schrieb:
> Somit schreibe ich die jeweiligen Variablen nur innerhalb EINES
> Prozesses
Du programmierst hier nicht mit Variablen, sondern mit Signalen. 
Variable sind in VHDL ganz was anderes. Aber lass da erst mal die Finger 
davon...

Ich würde deinen Code ein wenig umschreiben:
1
signal dcf_min1  : std_logic_vector (3 downto 0) := "0000";
2
signal dcf_min10 : std_logic_vector (2 downto 0) := "000";
3
signal dcf_hrs1  : std_logic_vector (3 downto 0) := "0000";
4
signal dcf_hrs10 : std_logic_vector (1 downto 0) := "00";
5
signal dcf_sr : std_logic_vector (2 downto 0) := "000";
6
signal dcf_cnt : integer range 0 to 2000 := 0;
7
signal dcf_sec : integer range 0 to 59 := 0;
8
signal dcf_bits : std_logic_vector (58 downto 0) := (others => '0');
9
signal onemscnt : integer range 0 to 499999 := 0; -- eine ms bei 50MHz
10
signal onems : std_logic := '0';
11
12
-- Den ms-Enable erzeugen
13
process begin 
14
  wait until rising_edge(clk);
15
  if (onemscnt < 49999) then
16
    onemscnt <= onemscnt +1;
17
    onems <= '0';
18
  else
19
    onemscnt <= 0;
20
    onems <= '1';                     -- für 1 clk Zyklus aktiv
21
  end if;
22
end process;
23
24
-- Einsynchronisieren
25
process begin 
26
  wait until rising_edge(clk);
27
  dcf_sr <= dcf_sr(1 downto 0) & dcf;
28
end process;
29
30
-- DCF-Signal auswerten
31
process  begin
32
  wait until rising_edge(clk);
33
  if (onems='1') then
34
     if (dcf_cnt<2000) then            -- zählen mit Begrenzung
35
        dcf_cnt <= dcf_cnt+1; 
36
     end if; 
37
     if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
38
        if (dcf_cnt<150) then          -- Null einschieben
39
          dcf_bits <= '0' & dcf_bits(58 downto 1);
40
        else                           -- Eins einschieben
41
          dcf_bits <= '1' & dcf_bits(58 downto 1);
42
        end if;
43
     end if;
44
     if (dcf_sr(2 downto 1)="01") then -- steigende Flanke  vom DCF-Signal
45
        if (dcf_cnt>1000) then         -- Sync --> Daten übernehmen
46
           dcf_min1  <= dcf_bits(23 downto 20); -- anpassen
47
           dcf_min10 <= dcf_bits(26 downto 24);
48
           dcf_hrs1  <= dcf_bits(xx downto zz);
49
           dcf_min10 <= dcf_bits(kk downto ww);
50
        end if;
51
        dcf_cnt <= 0;                  -- Zähler zurücksetzen
52
     end if;
53
  end if;
54
end process;

Da gehört jetzt noch ein wenig Fehlerbehandlung, aber prinzipiell könnte 
das schon gehen...

von VHDL-User (Gast)


Lesenswert?

voodoopuppe schrieb:
> als wir eine normale Uhr (ohne Funk-Zusatz) programmiert haben.

Hmm, immer wenn ich lese, dass jemand in VHDL PROGRAMMIERT hat (oder 
schreibt, dass das VHLD-PROGRAMM doch in der Simulation problemlos 
LÄUFT), weiß ich schon fast, mit welchen Problemen er zu kämpfen hat.

Man (be)schreibt etwas (nämlich eine Hardware) in VHDL. Und man muss 
anders denken als bei einer traditionellen Programmiersprache (für 
serielle Logik).

@Lothar: ich bewundere immer wieder Deine Geduld!

von VHDL-User (Gast)


Lesenswert?

Ähm, gerade gesehen:
1
-- Einsynchronisieren
2
process begin 
3
  wait until rising_edge(clk);
4
  dcf_sr <= dcf_sr(1 downto 0) & dcf;
5
end process;
6
7
-- DCF-Signal auswerten
8
process  begin
9
  wait until rising_edge(clk);
10
  if (onems='1') then
11
     if (dcf_cnt<2000) then            -- zählen mit Begrenzung
12
        dcf_cnt <= dcf_cnt+1; 
13
     end if; 
14
     if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
15
     .
16
     .
17
     .

Halte ich für problematisch: Die Wahrscheinlichkeit, dass der 
Flankenwechsel im richtigen Takt (if (onems='1')) kommt ist 1/50000!

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


Lesenswert?

VHDL-User schrieb:
> Die Wahrscheinlichkeit, dass der
> Flankenwechsel im richtigen Takt (if (onems='1')) kommt ist 1/50000!
Das ist gewünscht und hat mit Wahrscheinlichkeiten gar nichts zu tun. 
Denn das Signal kommt nicht mit einer Wahrscheinlichkeit, sondern 
garantiert genau jede Millisekunde. So kommt das Signal auch zu seinem 
Namen: "One Millisecond". Toll, nicht wahr... ;-)

Das ist übrigens genau die praktische Umsetzung des Clock-Enable aus dem 
Artikel Taktung FPGA/CPLD

von voodoopuppe (Gast)


Lesenswert?

Ich habe einmal eine Frage zu folgendem Code:
1
 wait until rising_edge(takt);
2
 if (onems='1') then
3
 sync <= '1';
4
  if (dcf_cnt < 2000) then            -- zählen mit Begrenzung
5
    dcf_cnt <= dcf_cnt+1; 
6
  end if;
7
  if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
8
  sync <= '1';
9
  if (dcf_cnt < 12) then          -- Null einschieben
10
   dcf_bits <= '0' & dcf_bits(58 downto 1);
11
    else                           -- Eins einschieben
12
   dcf_bits <= '1' & dcf_bits(58 downto 1);
13
    end if;
14
  end if;
15
  if (dcf_sr(2 downto 1)="01") then -- steigende Flanke  vom DCF-Signal
16
  sync <= '1'; 
17
    if (dcf_cnt > 1000) then         -- Sync --> Daten übernehmen
18
      dcf_min1  <= dcf_bits(23 downto 20); -- anpassen
19
      dcf_min10 <= dcf_bits(26 downto 24);
20
    end if;
21
    dcf_cnt <= 0;                  -- Zähler zurücksetzen
22
  end if;
23
 end if;
Bitte nicht über die geringen Werte bei dcf_cnt wundern - die sind 
gesetzt, damit sich das Ganze schneller simulieren lässt.

Es scheint so, als ob das Programm nie in den Zweig kommt, wo es auf 
fallende/steigende Flanke geprüft hat.
Denn egal, wie rum ich das sync <= '1'; da rein tu - es wird schlichtweg 
nicht ausgewertet. sync bleibt durchgängig 0.
In den onems='1'-Bereich kommt man rein, denn dort lässt sich sync noch 
setzen. Bei den Teilen danach jedoch nicht mehr.

Wie gesagt: es kommt mir so vor, als würde das Programm NIE in den 
Bereich nach den steigenden/fallenden Flanken kommen.
Woran das liegt, weiß ich absolut nicht.

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


Lesenswert?

voodoopuppe schrieb:
> Es scheint so, als ob das Programm nie in den Zweig kommt, wo es auf
> fallende/steigende Flanke geprüft hat.
Häng doch mal deinen VHDL-Code und deine Testbench als .vhd Dateien hier 
an...

Bei mir geht das... ;-)

von Falk (Gast)


Lesenswert?

Das Programm von Lothar hat noch ein paar andere "Fehler", aber ich 
denke mal das das von Lothar Absicht war, um dich ein wenig zum Denken 
anzuregen.


Schon allein dein Codeabschnitt strotzt nur so vor Fehlern, wundert mich 
das die Synthese überhaupt klappt.

1) dcf_count wird falsch zurückgesetzt
2) Deine Einrückungen sind grauselig zu lesen
3) Sync wird nie auf 0 gesetzt.
4) Fallende Flanke wird jede ms geprüft, steigende jedoch jeden Takt

Offensichtlich ist dir nicht klar, wann Signale gesetzt werden.

von Tron (Gast)


Lesenswert?

>hat es doch im Semester zuvor
>wunderbar geklappt, als wir eine normale Uhr (ohne Funk-Zusatz)
>programmiert haben.
Wer ist wir ? auf deinem Mist ist das sicherlich nicht gewachsen. Es 
fehlen dir wichtige Grundlagen.

>Halte ich für problematisch: Die Wahrscheinlichkeit, dass der
>Flankenwechsel im richtigen Takt (if (onems='1')) kommt ist 1/50000!
sehe ich genauso.

>Denn das Signal kommt nicht mit einer Wahrscheinlichkeit, sondern
>garantiert genau jede Millisekunde.
das ist richtig, aber dcf_count und auch onemscount wird nie auf 
irgendetwas synchronisiert.

@lothar
Du synchronisiert zwar dcf auf den Takt mit 2 FF, aber bei der 
Flankenabfrage benutzt du schon eines der Beiden FF, ist das gewollt ?

von voodoopuppe (Gast)


Lesenswert?

"1) dcf_count wird falsch zurückgesetzt"
Ist im Grunde vollkommen egal - da man ja anscheinend nicht mal bis zum 
entsprechendem Punkt im Code kommt, wo ein Rücksetzen Sinn machen 
könnte.

"2) Deine Einrückungen sind grauselig zu lesen"
Sind hier aus dem Forum zum ausprobieren des Codes so übernommen - macht 
im Code selbst auch keinen Unterschied, wie das nun eingerückt ist ....

"3) Sync wird nie auf 0 gesetzt."
Es wird beim Reset auf 0 gesetzt. Warum sollte ich es an einer anderen 
Stelle noch einmal auf 0 setzen, wenn ich das gar nicht will?!

"4) Fallende Flanke wird jede ms geprüft, steigende jedoch jeden Takt"
Komisch - wenn diese Flanke IM "1ms" drin steht, sollte die Flanke auch 
jede MS - und nicht jeden Takt - geprüft werden.
Eventuell den Code einfach nochmal lesen?
Ich vereinfache es dir noch einmal:
1
wait until rising_edge(takt);
2
if (onems='1') then
3
  sync <= '1';
4
  if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
5
    sync <= '1';
6
  end if;
7
  if (dcf_sr(2 downto 1)="01") then -- steigende Flanke  vom DCF-Signal
8
    sync <= '1';
9
  end if; 
10
end if;
Für mich sieht das so aus, als würde sowohl fallende als auch steigende 
Flanke jede ms geprüft. Sollte dem nicht so sein - berichtige mich ....

"Schon allein dein Codeabschnitt strotzt nur so vor Fehlern, wundert 
mich
das die Synthese überhaupt klappt."
Dann zeige mir diese FEHLER bitte auf. Scheinbar muss es sich um massive 
Logikfehler handeln - denn beim synthetisieren bekomme ich zumindest 
keine Fehler ....
Also: Wo stecken hier die massiven Fehler? Oder war das etwa deine 
Aufzählung, die ich dir oben näher erläutert habe? Wenn ja war das ja 
wohl nichts.

"Wer ist wir ? auf deinem Mist ist das sicherlich nicht gewachsen."
Nun, glücklicherweise habe ich das Projekte damals fast allein umgesetzt 
- trotz zweier Gruppen. Mag sein, dass ein paar einfache Zählschleifen 
etwas einfacher sind als dieses Programm, wo man auf zwei verschiedene 
Signale reagieren muss. Ist auch vollkommen egal, auf diese 
Unterstellungen lasse ich mich mal gar nicht weiter ein.

@Lothar Miller
Ich lade das Freitag Nachmittag/Abend mal hoch. Sowohl die vhd als auch 
die vhst (? hieß glaub ich so).

Danke so weit für die Hilfe. Warum das Stückchen so nicht funktioniert 
und mir die sync-Ausgänge nicht belegt, begreife ich leider nicht. Es 
kann eigentlich nur die Abfrage nach den Flanken sein, die fehlerhaft 
ist. Aber da das so oft im Netz so beschrieben wird, müsste es doch 
eigentlich (!) gehen.

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


Angehängte Dateien:

Lesenswert?

Da ging beim vorigen Beitrag mit den Anhängen was schief... :-(

Falk schrieb:
> Das Programm von Lothar hat noch ein paar andere "Fehler", aber ich
> denke mal das das von Lothar Absicht war, um dich ein wenig zum Denken
> anzuregen.
Ich habe das aus dem Kopf schnell hingeschreiben, und der Syntaxcheck 
hier im Forum tut noch nicht so richtig... ;-)
Wobei: Syntaxfehler waren nicht mal drin (abgesehen von der 499999), 
aber ein Denkfehler beim Einsynchronisieren des dcf-Signals. Bis da mal 
auf die Flanken abgefragt wird, ist das Schieberegister schon längst 
"000" oder "111". Und deshalb wird keine Flanke erkannt.
Abhilfe schafft, das Eintakten in den ms-Takt zu übernehmen:
1
   -- Einsynchronisieren
2
   process begin 
3
     wait until rising_edge(clk);
4
     if (onems='1') then
5
        dcf_sr <= dcf_sr(1 downto 0) & dcf;
6
     end if;
7
   end process;
oder so:
1
   process  begin
2
     wait until rising_edge(clk);
3
     if (onems='1') then
4
5
        dcf_sr <= dcf_sr(1 downto 0) & dcf; -- Asynchrones Signal einsynchronisieren
6
7
        if (dcf_cnt<2000) then            -- zählen mit Begrenzung
8
           dcf_cnt <= dcf_cnt+1; 
9
        end if; 
10
        :

Tron schrieb:
> @lothar
> Du synchronisiert zwar dcf auf den Takt mit 2 FF, aber bei der
> Flankenabfrage benutzt du schon eines der Beiden FF, ist das gewollt ?
Ja, zum Einsynchronisieren sind 2 FFs nötig. Das mittlere der dreien ist 
schon das zweite ;-)

voodoopuppe schrieb:
> @Lothar Miller
> Ich lade das Freitag Nachmittag/Abend mal hoch. Sowohl die vhd als auch
> die vhst (? hieß glaub ich so).
Was ist die vhst?
Meine Testbench heißt zum Nachnamen auch .vhd  :-o

von VHDL-User (Gast)


Lesenswert?

Lothar Miller schrieb:
> ..aber ein Denkfehler beim Einsynchronisieren des dcf-Signals. Bis da mal
> auf die Flanken abgefragt wird, ist das Schieberegister schon längst
> "000" oder "111".

...das meinte ich oben mit der Wahrscheinlichkeit :-)

von voodoopuppe (Gast)


Lesenswert?

>Ja, zum Einsynchronisieren sind 2 FFs nötig. Das mittlere der dreien ist
>schon das zweite ;-)
ROFL

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


Lesenswert?

VHDL-User schrieb im Beitrag #2017319:
> ...das meinte ich oben mit der Wahrscheinlichkeit :-)
Stimmt. Hätte mich stutzig machen müssen...   :-/

von voodoopuppe (Gast)


Lesenswert?

Hi,

ich bin mittlerweile ganz gut voran gekommen.
Habe lediglich ein paar kleinere Fehlerchen festgestellt, die ich 
behoben habe - unter anderem fiel mir irgendwann auf, dass es ja 
zwischen sekunden, milisekunden und nanosekunden auch noch die 
mikrosekunden gibt ..... das hat die meisten Probleme behoben .... keine 
Ahnung, was mich bei der Umrechnung von MHz in Sekunden geritten hat - 
jetzt funktioniert es jedenfalls.

Danke für die Hilfe, morgen mache ich intensiv weiter und schaue mal, 
wie weit ich komme. Es fehlt lediglich noch das Verarbeiten der Daten in 
den entsprechenden "Bauteilen".

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.