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
signalcount:integer0to50;
5
signalpulseState:std_logic;
6
begin
7
process(clk)
8
ifrising_edge(clk)then
9
ifcountTo>countthen
10
count=count+1
11
else
12
pulseState<=notpulseState;
13
count<=0;
14
endif;
15
endif;
16
endprocess;
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
ifrising_edge(freqOut)
7
....
8
endif;
9
endprocess;
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
signalidle:boolean;
5
begin
6
process(clk,freqOut)
7
ifrising_edge(clk)
8
9
if(freqOut='1')then
10
idle<=false;
11
12
if(idle=true)then
13
-- Tu was
14
15
endif;
16
17
else--wenn freqOut = 0
18
idle<=true;
19
endif;
20
21
endif;
22
endprocess;
23
end;
Stimmt dieser Ansazt oder wie löst man sowas?
Danke
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.
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.
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.
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
signalcount:integer0to99:=0;
3
signalenOut:std_logic:='0';
4
begin
5
6
process(clk)
7
ifrising_edge(clk)then
8
ifcount<99then-- 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
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.
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.
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.
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]
######
@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:
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.