Forum: FPGA, VHDL & Co. Geteilten Takt weiterverwenden


von Holger K. (holgerkraehe)


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:
1
  
2
....
3
architecture
4
  signal count: integer 0 to 50;
5
  signal pulseState: std_logic;
6
begin
7
  process(clk)
8
    if rising_edge(clk) then
9
      if countTo > count then 
10
        count = count + 1
11
      else
12
        pulseState <= not pulseState;
13
        count <= 0;
14
      end if;
15
    end if;
16
  end process;
17
18
  freqOut <= pulseState;
19
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:
1
...
2
architecture
3
4
begin
5
  process(freqOut)
6
    if rising_edge(freqOut)
7
      ....
8
    end if;    
9
  end process;
10
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:
1
...
2
3
architecture
4
  signal idle:boolean;
5
begin
6
  process(clk, freqOut)
7
    if rising_edge(clk)
8
9
      if(freqOut = '1') then 
10
        idle <= false;
11
12
        if(idle = true) then
13
          -- Tu was 
14
15
        end if;
16
17
     else --wenn freqOut = 0
18
       idle <= true;
19
     end if;
20
          
21
    end if;    
22
  end process;
23
end;

Stimmt dieser Ansazt oder wie löst man sowas?

Danke

von Markus F. (mfro)


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)


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)


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)


Lesenswert?

Vielen Dank für deine Antwort.

Ich werde das also so versuchen.

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


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:
1
architecture
2
  signal count: integer 0 to 99 := 0;
3
  signal enOut : std_logic := '0';
4
begin
5
6
  process(clk)
7
    if rising_edge(clk) then
8
      if count < 99 then -- Teiler durch 100
9
        count = count + 1;
10
        enOut <= '0'  -- das Enable ist für 99 Taktzyklen inaktiv
11
      else
12
        count <= 0;
13
        enOut <= '1'  -- das Enable ist für 1 Taktzyklus aktiv
14
      end if;
15
    end if;
16
  end process;
17
18
  process(clk)
19
    if rising_edge(clk)
20
      if(enOut = '1') then -- ist Enable aktiv?
21
          -- Tu was - jeweils nach 100 Taktzyklen
22
      end if;
23
    end if;    
24
  end process;
25
26
end;

: Bearbeitet durch Moderator
von VHDL-Polizei (Gast)


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


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. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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)


Lesenswert?


von Jürgen S. (engineer) Benutzerseite


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:

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)


Lesenswert?

1
  process(clk)
2
  begin
3
    if (rising_edge(clk)) then
4
      if (lowFreq = '1') then
5
        LEDstate <= not LEDstate;
6
      end if;
7
8
    end if;
9
10
  end process;
11
12
  LED <= LEDstate;

von Holger K. (holgerkraehe)


Angehängte Dateien:

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:
1
  process(clk)
2
  begin
3
    if (rising_edge(clk)) then
4
      if (lowFreq = '1') then
5
        LEDstate <= not LEDstate;
6
      end if;
7
8
    end if;
9
10
  end process;
11
12
  LED <= LEDstate;

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


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.

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.