mikrocontroller.net

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


Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
    if(reset = '1') then
      timer_hh <= 0;
      sek_nr  <= 0;
      zustand  <= 0;
    end if;
    
    if(rising_edge(takt)) then
      timer_hh <= timer_hh+1;
    end if;
    if(falling_edge(dcf)) then
      -- hier beginnen wir mit dem zaehlen
      timer_hh <= 0;
    elsif(rising_edge(dcf)) then
      -- zaehler stoppen und Zeit auswerten
      if(timer_hh = 200) then
      -- jetzt haben wir eine 1 bekommen
        sek_nr <= sek_nr + 1;
      elsif(timer_hh = 100) then
      -- jetzt haben wir eine 0 bekommen
        sek_nr <= sek_nr + 1;
      elsif(timer_hh > 500) then
      -- jetzt sind wir synchron zur Minute
        sek_nr <= 0;
      end if;
    end if;

Dieser Code funktioniert problemlos (zumindest was das synthetisieren 
angeht).
    if(reset = '1') then
      timer_hh <= 0;
      sek_nr  <= 0;
      zustand  <= 0;
    end if;
    
    if(rising_edge(takt)) then
      timer_hh <= timer_hh+1;
    end if;
    if(falling_edge(dcf)) then
      -- hier beginnen wir mit dem zaehlen
      timer_hh <= 0;
    elsif(rising_edge(dcf)) then
      -- zaehler stoppen und Zeit auswerten
      if(timer_hh = 200) then
      -- jetzt haben wir eine 1 bekommen
        sek_nr <= sek_nr + 1;
      elsif(timer_hh = 100) then
      -- jetzt haben wir eine 0 bekommen
        sek_nr <= sek_nr + 1;
      elsif(timer_hh > 500) then
      -- jetzt sind wir synchron zur Minute
        sek_nr <= 0;
        sync <= '1';
      end if;
    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?

Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bevor ich es vergesse:
    if(timer_hh > 5) then
      sync <= '1';
    else
      sync <= '0';
    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:
--DCF77Block


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;


entity dcf77 is

  port
  (
    dcf    : in   std_logic;
    takt    : in  std_logic;
    reset    : in   std_logic;
    sync    : out std_logic;
    sync_lvl  : out std_logic_vector(1 downto 0);
    out_min  : out std_logic_vector(5 downto 0);
    out_std  : out std_logic_vector(5 downto 0);
    out_tag  : out std_logic_vector(5 downto 0);
    out_mon  : out std_logic_vector(5 downto 0);
    out_jhr  : out std_logic_vector(5 downto 0)
  );

end entity;

-- Programmablauf:
-- warte auf fallende Flanke
-- 


architecture verhalten of dcf77 is
  signal zustand    : integer := 0;
  -- sek_nr bestimmt Position innerhalb der laufenden Minute
  signal sek_nr    : integer := 0;
  -- timer tiefhoch
  signal timer_hh  : integer := 0;
  signal temp      : integer := 0;
begin
  
  process (dcf, reset, takt)
  begin
    -- Zustand 0: Programmstart
    -- Zustand 1: Programm laeuft und hat erste fallende Flanke gefunden
    -- Zustand 2: Programm ist synchron
    if(reset = '1') then
      timer_hh <= 0;
      sek_nr  <= 0;
      zustand  <= 0;
    end if;
    
    if(rising_edge(takt)) then
      timer_hh <= timer_hh+1;
    end if;
    if(falling_edge(dcf)) then
      -- hier beginnen wir mit dem zaehlen
      timer_hh <= 0;
    elsif(rising_edge(dcf)) then
      -- zaehler stoppen und Zeit auswerten
      if(timer_hh = 200) then
      -- jetzt haben wir eine 1 bekommen
        sek_nr <= sek_nr + 1;
      elsif(timer_hh = 100) then
      -- jetzt haben wir eine 0 bekommen
        sek_nr <= sek_nr + 1;
      elsif(timer_hh > 500) then
      -- jetzt sind wir synchron zur Minute
        sek_nr <= 0;
      end if;
    end if;
    
    if(timer_hh > 5) then
      sync <= '1';
    else
      sync <= '0';
    end if;
    
  end process;
  
end verhalten;  

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
if(dcfsig = 1) then
--Zeitmessen;
dcfsig = 0;
end if;[VHDL]
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.

Um es mal ein wenig codetechnisch darzustellen:
[vhdl]
process begin
  wait until rising_edge(dcf);
  dcfok <= 1;
end process;

process  begin
  wait until rising_edge(takt);
  timer_hh <= timer_hh+1;
end process;

process begin
  if(dcfok = 1)
    -- do sth
    timer_hh <= 0;
    dcfok <= 0;
  end if;
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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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):
process  begin
  wait until rising_edge(takt);
  if(dcf = '1') then
    timer_hh <= timer_hh+1;
  end if;
end process;

process begin
  if(dcf = '0') then
    if(zustand = 1) then
      if(timer_hh = 900) then
        -- wir haben ne 0
      elsif(timer_hh = 800) then
        -- wir haben ne 1
      elsif(timer_hh > 1000) then
        -- wir haben ne neue Sekunde
      end if;
    timer_hh <= 0;
    zustand <= 0;
  end if;
  elsif(dcf = '1') then
    zustand <= 1;
  end if;
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:
process  begin
  wait until rising_edge(takt);
  if(dcf = '1') then
    timer_hh <= timer_hh+1;
  end if;
  if(zustand = 0) then
    timer_hh <= 0;
  end if;
end process;

process begin
  if(dcf = '0') then
    if(zustand = 1) then
      if(timer_hh = 900) then
        -- wir haben ne 0
      elsif(timer_hh = 800) then
        -- wir haben ne 1
      elsif(timer_hh > 1000) then
        -- wir haben ne neue Sekunde
      end if;
    zustand <= 0;
  end if;
  elsif(dcf = '1') then
    zustand <= 1;
  end if;
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? ;)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
signal dcf_min1  : std_logic_vector (3 downto 0) := "0000";
signal dcf_min10 : std_logic_vector (2 downto 0) := "000";
signal dcf_hrs1  : std_logic_vector (3 downto 0) := "0000";
signal dcf_hrs10 : std_logic_vector (1 downto 0) := "00";
signal dcf_sr : std_logic_vector (2 downto 0) := "000";
signal dcf_cnt : integer range 0 to 2000 := 0;
signal dcf_sec : integer range 0 to 59 := 0;
signal dcf_bits : std_logic_vector (58 downto 0) := (others => '0');
signal onemscnt : integer range 0 to 499999 := 0; -- eine ms bei 50MHz
signal onems : std_logic := '0';

-- Den ms-Enable erzeugen
process begin 
  wait until rising_edge(clk);
  if (onemscnt < 49999) then
    onemscnt <= onemscnt +1;
    onems <= '0';
  else
    onemscnt <= 0;
    onems <= '1';                     -- für 1 clk Zyklus aktiv
  end if;
end process;

-- Einsynchronisieren
process begin 
  wait until rising_edge(clk);
  dcf_sr <= dcf_sr(1 downto 0) & dcf;
end process;

-- DCF-Signal auswerten
process  begin
  wait until rising_edge(clk);
  if (onems='1') then
     if (dcf_cnt<2000) then            -- zählen mit Begrenzung
        dcf_cnt <= dcf_cnt+1; 
     end if; 
     if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
        if (dcf_cnt<150) then          -- Null einschieben
          dcf_bits <= '0' & dcf_bits(58 downto 1);
        else                           -- Eins einschieben
          dcf_bits <= '1' & dcf_bits(58 downto 1);
        end if;
     end if;
     if (dcf_sr(2 downto 1)="01") then -- steigende Flanke  vom DCF-Signal
        if (dcf_cnt>1000) then         -- Sync --> Daten übernehmen
           dcf_min1  <= dcf_bits(23 downto 20); -- anpassen
           dcf_min10 <= dcf_bits(26 downto 24);
           dcf_hrs1  <= dcf_bits(xx downto zz);
           dcf_min10 <= dcf_bits(kk downto ww);
        end if;
        dcf_cnt <= 0;                  -- Zähler zurücksetzen
     end if;
  end if;
end process;

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

Autor: VHDL-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: VHDL-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, gerade gesehen:
-- Einsynchronisieren
process begin 
  wait until rising_edge(clk);
  dcf_sr <= dcf_sr(1 downto 0) & dcf;
end process;

-- DCF-Signal auswerten
process  begin
  wait until rising_edge(clk);
  if (onems='1') then
     if (dcf_cnt<2000) then            -- zählen mit Begrenzung
        dcf_cnt <= dcf_cnt+1; 
     end if; 
     if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
     .
     .
     .

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe einmal eine Frage zu folgendem Code:
 wait until rising_edge(takt);
 if (onems='1') then
 sync <= '1';
  if (dcf_cnt < 2000) then            -- zählen mit Begrenzung
    dcf_cnt <= dcf_cnt+1; 
  end if;
  if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
  sync <= '1';
  if (dcf_cnt < 12) then          -- Null einschieben
   dcf_bits <= '0' & dcf_bits(58 downto 1);
    else                           -- Eins einschieben
   dcf_bits <= '1' & dcf_bits(58 downto 1);
    end if;
  end if;
  if (dcf_sr(2 downto 1)="01") then -- steigende Flanke  vom DCF-Signal
  sync <= '1'; 
    if (dcf_cnt > 1000) then         -- Sync --> Daten übernehmen
      dcf_min1  <= dcf_bits(23 downto 20); -- anpassen
      dcf_min10 <= dcf_bits(26 downto 24);
    end if;
    dcf_cnt <= 0;                  -- Zähler zurücksetzen
  end if;
 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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... ;-)

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tron (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
wait until rising_edge(takt);
if (onems='1') then
  sync <= '1';
  if (dcf_sr(2 downto 1)="10") then -- fallende Flanke vom DCF-Signal
    sync <= '1';
  end if;
  if (dcf_sr(2 downto 1)="01") then -- steigende Flanke  vom DCF-Signal
    sync <= '1';
  end if; 
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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
   -- Einsynchronisieren
   process begin 
     wait until rising_edge(clk);
     if (onems='1') then
        dcf_sr <= dcf_sr(1 downto 0) & dcf;
     end if;
   end process;
oder so:
   process  begin
     wait until rising_edge(clk);
     if (onems='1') then

        dcf_sr <= dcf_sr(1 downto 0) & dcf; -- Asynchrones Signal einsynchronisieren

        if (dcf_cnt<2000) then            -- zählen mit Begrenzung
           dcf_cnt <= dcf_cnt+1; 
        end if; 
        :

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

Autor: VHDL-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: voodoopuppe (Gast)
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

Autor: voodoopuppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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".

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.