Forum: FPGA, VHDL & Co. Geteilten Takt weiterverwenden


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich bin neu in der FPGA/VHDL Welt.
Stehe aktuell vor folgendem Problem:

Ich möchte einen Takt teilen und diesen dann weiterverwenden.

[50MHz] -> [Teiler mit Counter] -> [Zweite Zählstufe] -> [z.b. LED]

Den Teiler kriege ich relativ leicht hin:
  
....
architecture
  signal count: integer 0 to 50;
  signal pulseState: std_logic;
begin
  process(clk)
    if rising_edge(clk) then
      if countTo > count then 
        count = count + 1
      else
        pulseState <= not pulseState;
        count <= 0;
      end if;
    end if;
  end process;

  freqOut <= pulseState;
end;


Nun habe ich gelernt, dass es unschön ist, wenn man asynchrone Takte 
verwendet.

Der einfachste Weg, die nächste Stufe zu takten wäre ja, das freqOut 
signal zu verwenden, in etwa so:
...
architecture

begin
  process(freqOut)
    if rising_edge(freqOut)
      ....
    end if;    
  end process;
end;

Statdessen soll man ja das ganze synchron zum MasterClock halten.
Hier beginnt das Problem für mich.
Wie synchronisiere ich nun meine heruntergeteilte Frequenz zum 
Haupttakt?

Dies war mein bisheriger Ansatz:
...

architecture
  signal idle:boolean;
begin
  process(clk, freqOut)
    if rising_edge(clk)

      if(freqOut = '1') then 
        idle <= false;

        if(idle = true) then
          -- Tu was 

        end if;

     else --wenn freqOut = 0
       idle <= true;
     end if;
          
    end if;    
  end process;
end;

Stimmt dieser Ansazt oder wie löst man sowas?

Danke

von Markus F. (mfro)


Bewertung
1 lesenswert
nicht lesenswert
Holger K. schrieb:
> Nun habe ich gelernt, dass es unschön ist, wenn man asynchrone Takte
> verwendet.

unschön ist, Takte, die keine sind, als Takte zu verwenden.

Takte deine "langsamen" Prozesse mit dem schnellen (idealerweise 
einzigen) Takt (ohne an dem rumzufummeln) und nimm dein Zähler-Signal 
als enable.

Damit bleibt das Design synchron.

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Markus F. schrieb:
> Takte deine "langsamen" Prozesse mit dem schnellen (idealerweise
> einzigen) Takt (ohne an dem rumzufummeln) und nimm dein Zähler-Signal
> als enable.

Genau das versuche ich ja im letzten Code-Beispiel.
Hast du dir das angeschaut?

Meine Frage war ja, ob dies so richtig implementiert ist, oder wie man 
es sonst machen würde.

von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Holger K. schrieb:
> Wie synchronisiere ich nun meine heruntergeteilte Frequenz zum
> Haupttakt?

Markus F. schrieb:
> unschön ist, Takte, die keine sind, als Takte zu verwenden.

Dein freqOut ist synchron zu deinem MasterClock, da du dieses Signal ja 
in einem synchronen Prozess beschreibst. Es ist also keine weitere 
Synchronisation nötig.

Darum wohl auch der Hinweis von Markus F., dass dein freqOut gar kein 
Takt ist. Besser du nennst das <was es steuert>Enable. Bei dir z. B. 
LedCountEnable.

Holger K. schrieb:
> Stimmt dieser Ansazt oder wie löst man sowas?

Ja, genau so.

Wenn du möchtest, kannst du beide Teile auch im selben Prozess 
beschreiben aber das ist eine reine Stilfrage.

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für deine Antwort.

Ich werde das also so versuchen.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Holger K. schrieb:
> process(clk, freqOut)
freqOut ist hier unnötig. In einem synchronen Prozess (ohne 
asynchronen Reset) steht lediglich der eine FPGA-Mastertakt in der 
Sensitivliste.

> signal count: integer 0 to 50;
Die 50 deutet hier auf den beliebten Off-By-One Fehler hin...

> idle <= false;
> idle <= true;
Das idle hier ist irgendwie unnötig bzw. umständlich, weil es 
lediglich die "invertierte" und um einen Takt versetzte Version des 
freqOut ist.

Mach dein freqOut so, dass es nur 1 Taktzyklus lang gültig ist. Und 
nenne es sinnvollerweise gleich enOut. Dann kannst du direkt mit 
diesem Signal als Enable arbeiten und musst nicht noch eine 
Flankenerkennung dazubasteln:
architecture
  signal count: integer 0 to 99 := 0;
  signal enOut : std_logic := '0';
begin

  process(clk)
    if rising_edge(clk) then
      if count < 99 then -- Teiler durch 100
        count = count + 1;
        enOut <= '0'  -- das Enable ist für 99 Taktzyklen inaktiv
      else
        count <= 0;
        enOut <= '1'  -- das Enable ist für 1 Taktzyklus aktiv
      end if;
    end if;
  end process;

  process(clk)
    if rising_edge(clk)
      if(enOut = '1') then -- ist Enable aktiv?
          -- Tu was - jeweils nach 100 Taktzyklen
      end if;
    end if;    
  end process;

end;

: Bearbeitet durch Moderator
von VHDL-Polizei (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Markus F. schrieb:
> unschön ist, Takte, die keine sind, als Takte zu verwenden.

hätte man kaum besser formulieren können.

von Josef G. (bome) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
VHDL-Polizei schrieb im Beitrag #5590245:
> Markus F. schrieb:
>> unschön ist, Takte, die keine sind, als Takte zu verwenden.
>
> hätte man kaum besser formulieren können.

Ob das ein Takt ist, hängt vom Routing ab.

Wenn man es auf einen Clock-Buffer aufschaltet und
über das Taktnetz verteilt, dann ist es ein Takt.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Josef G. schrieb:
> VHDL-Polizei schrieb:
>> Markus F. schrieb:
>>> unschön ist, Takte, die keine sind, als Takte zu verwenden.
>> hätte man kaum besser formulieren können.
> Ob das ein Takt ist, hängt vom Routing ab.
> Wenn man es auf einen Clock-Buffer aufschaltet und
> über das Taktnetz verteilt, dann ist es ein Takt.
Wenn am "anderen Ende" irgendein Takteingang sitzt, dann ist es ein 
Takt. Wie das Signal zu diesem Takteingang kommt (ob durch ein Taktnetz 
oder durch direktes Routing), ist nachrangig.

Oder andersrum: ein Signal, das z.B. SPI_CLK (SCLK) oder I2C_CLK (SCL) 
heißt, sollte deswegen noch lange nicht wie ein Taktsignal behandelt und 
als Takt auf ein Flipflop gegeben werden.

: Bearbeitet durch Moderator
von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert

von Jürgen S. (engineer) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Josef G. schrieb:
> Ob das ein Takt ist, hängt vom Routing ab.
Sagen wir mal, "ob ein Taktnetz verwendet wird / werden kann" hängt von 
Routing ab und dies hängt vom Chip und den Positionen ab. Ob es dann 
gemacht wird, werden muss, hängt wiederum von der Beschreibung ab. Siehe 
Lothars Kommentar.

Das Problem dabei ist, dass man eben sehr viel mehr beschrieben kann, 
kann machbar ist, leider aber auch einiges beschreiben kann, was unnötig 
ist und ungünstig.

> Wenn man es auf einen Clock-Buffer aufschaltet und
> über das Taktnetz verteilt, dann ist es ein Takt.
Das erfordert aber händisches design und das ist oftmals 
kontraproduktiv.
Zudem sind dann vor dem buffer oft keine dedizierten Taktresourcen 
genutzt, weder in Sachen Leitung noch Generation. Takte baut man nicht 
umsonst über PLLs oder DCMs.

Und zu allem kommt noch die Thematik der Verifikation durch das tool. 
Nicht alles, was man bauen kann, wird auch automatisch unterstützt.

Die händische Taktteilerei, wie wir sie außerhalb von FPGAs mit Chips 
realisieren, oder mit programmierbaren OSCs, war für PLDs noch eine 
gängige Praxis. Sie passt aber nicht mehr zu heutigen Methoden des FPGA 
designs.

Falk B. schrieb:
> Taktung FPGA/CPLD
Guter link, allerdings habe ich da gerade was Suboptimales zur Taktung 
gefunden. Werde es mal überarbeiten.

von Holger K. (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Das idle hier ist irgendwie unnötig bzw. umständlich, weil es
> lediglich die "invertierte" und um einen Takt versetzte Version des
> freqOut ist.

Vielen Dank für deine Antwort.

Ich habe dies nun so veruscht umzusetzen und habe es grundsätzlich auch 
geschafft. Was mich jedoch noch etwas stört ist, dass die Ausgabe erst 
um einen Takt versetzt stattfindet, wie du bereits geschrieben hast.

Gibt es eine möglichkeit, diese nicht um einen Takt versetzt auszugeben?

Hier mein Vorgehen:

[MCLK]->[delay_gen2]->enOut->[enIn delay_gen_en]->enOut->[main Process]

Vom master Clock (clk) geht es an das erste Modul namens delay_gen2.
Dieses soll den Clock um Faktor 5 Teilen. Es generiert ein enOut signal.
Dieses Signal wird beim Modul delay_gen_en als Eingang verwendet und 
zusammen mit clk als Takt verwendet. Das zweite Modul soll um Faktor 3 
teilen.

Dieses Modul erzeugt ebenfalls ein enOut signal, welches im main process 
eine virtuelle LED ansteuern soll.

Nun ergeben sich leider pro modul ein Versatz um einen Takt.
Wie kann man dies umgehen?

Hintergrund:
Ich möchte ein LCD mit Parallelinterface (HSYNC, VSYNC etc.) ansteuern.
Um das Timing möglichst bequem beschreiben zu können, wollte ich mir 
zuerst ein gängiges "Frequenz" Modul bauen. Ob ein Versatz um einen Takt 
ein Problem sein wird, denke ich mal nicht, da ich einfach bei der 
Vorstufe -1 Takt delay einstellen kann.

Jedoch weiss ich nicht, ob solch ein Design mit einem Takt versatz 
"unschön" ist oder ob es sich überhaupt "optmieren" lässt.
Habe diesbezüglich leider keine Erfahrungen. Oder ist sowas schlicht 
"egal"?

Die Module sind im Anhang.

Danke!

main process:
[vhdl]
  process(clk)
  begin
    if (rising_edge(clk)) then
      if (lowFreq = '1') then
        LEDstate <= not LEDstate;
      end if;

    end if;

  end process;

  LED <= LEDstate;
[\vhdl]

von Holger K. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
  process(clk)
  begin
    if (rising_edge(clk)) then
      if (lowFreq = '1') then
        LEDstate <= not LEDstate;
      end if;

    end if;

  end process;

  LED <= LEDstate;

von Holger K. (holgerkraehe)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
######
@MOD: Bitte obige Doppel-fehl-Posts löschen. Danke!

Lothar M. schrieb:
> Das idle hier ist irgendwie unnötig bzw. umständlich, weil es
> lediglich die "invertierte" und um einen Takt versetzte Version des
> freqOut ist.

Vielen Dank für deine Antwort.

Ich habe dies nun so veruscht umzusetzen und habe es grundsätzlich auch
geschafft. Was mich jedoch noch etwas stört ist, dass die Ausgabe erst
um einen Takt versetzt stattfindet, wie du bereits geschrieben hast.

Gibt es eine möglichkeit, diese nicht um einen Takt versetzt auszugeben?

Hier mein Vorgehen:

[MCLK]->[delay_gen2]->enOut->[enIn delay_gen_en]->enOut->[main Process]

Vom master Clock (clk) geht es an das erste Modul namens delay_gen2.
Dieses soll den Clock um Faktor 5 Teilen. Es generiert ein enOut signal.
Dieses Signal wird beim Modul delay_gen_en als Eingang verwendet und
zusammen mit clk als Takt verwendet. Das zweite Modul soll um Faktor 3
teilen.

Dieses Modul erzeugt ebenfalls ein enOut signal, welches im main process
eine virtuelle LED ansteuern soll.

Nun ergeben sich leider pro modul ein Versatz um einen Takt.
Wie kann man dies umgehen?

Hintergrund:
Ich möchte ein LCD mit Parallelinterface (HSYNC, VSYNC etc.) ansteuern.
Um das Timing möglichst bequem beschreiben zu können, wollte ich mir
zuerst ein gängiges "Frequenz" Modul bauen. Ob ein Versatz um einen Takt
ein Problem sein wird, denke ich mal nicht, da ich einfach bei der
Vorstufe -1 Takt delay einstellen kann.

Jedoch weiss ich nicht, ob solch ein Design mit einem Takt versatz
"unschön" ist oder ob es sich überhaupt "optmieren" lässt.
Habe diesbezüglich leider keine Erfahrungen. Oder ist sowas schlicht
"egal"?

Die Module sind im Anhang.

Danke!

main process:
  process(clk)
  begin
    if (rising_edge(clk)) then
      if (lowFreq = '1') then
        LEDstate <= not LEDstate;
      end if;

    end if;

  end process;

  LED <= LEDstate;

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Holger K. schrieb:
> Oder ist sowas schlicht "egal"?
In diesem Fall hier ist diese Latency mit an Sicherheit grenzender 
Wahrscheinlichkeit irrelevant... 😉

> Wie kann man dies umgehen?
Man fragt den Zählerstand direkt (statt des Enables) ab, oder man 
erzeugt das Enable einen Takt früher.

> Dieses Modul
Im ersten Fall ist es sinnvoll, nicht jeden kleinen Zähler in ein 
eigenes Modul zu packen, sondern ein einziges Modul zu machen, das die 
Ansteuerung komplett enthält.
Das wäre dann auch mein Ansatz.

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.