Hallo. Ich hab mir folgendes für einen Counter(umzusetzen in VHDL und auch auf ein FPGA zu bringen) überlegt: Ich hab einen synchronen Reset Eingang. Jetzt will ich aber, das wenn ich den reset setze, das der counter auf 0 zurückspringt und dann, obwohl der reset noch auf 1 ist, ganz normal weiterzählt. Erst bei der nächsten steigenden Flanke vom reset soll wieder auf 0 zurückgesetzt werden, und nicht, das der Counter die ganze Zeit auf 0 bleibt solange rst = 1. Macht man sowas? Führt das zu einer "unglücklichen"(sprich ineffizienten) HW? Grüße
vhdl-anfänger schrieb: > Hallo. > Ich hab mir folgendes für einen Counter(umzusetzen in VHDL und auch auf > ein FPGA zu bringen) überlegt: > Ich hab einen synchronen Reset Eingang. Jetzt will ich aber, das wenn > ich den reset setze, das der counter auf 0 zurückspringt und dann, > obwohl der reset noch auf 1 ist, ganz normal weiterzählt. Erst bei der > nächsten steigenden Flanke vom reset soll wieder auf 0 zurückgesetzt > werden, und nicht, das der Counter die ganze Zeit auf 0 bleibt solange > rst = 1. > Macht man sowas? Führt das zu einer "unglücklichen"(sprich > ineffizienten) HW? > Grüße in etwa so? process(clk) if rising_edge(clk) then reset_delayed <= reset; if reset = '1' and reset_delayed = '0' then count_q <= 0; else count_q <= count_q + 1; end if; end if; end process; Sollte kein problem sein.
vhdl-anfänger schrieb: > scheint zu funktionieren.^^ Das Speichern des vorigen Zustands und der Vergleich mit dem aktuellen zustand nennt sich "Flankenerkennung". Die braucht man öfter mal...
ich weiß... ich wusste nur nicht wie ich das hier so formulieren kann... Hehe manchmal gehts nicht besser
Werktätiger schrieb:
1 | (1) if rising_edge(clk) then |
2 | (2) reset_delayed <= reset; |
3 | (3) if reset = '1' and reset_delayed = '0' then |
4 | (4) count_q <= 0; |
Entsteht hier nicht eine Racecondition? Die Zuweisung (2) passiert ja quasi gleichzeitig mit dem Vergleich (3), also würde (4) eigentlich eher selten ausgeführt. Besser wäre glaube ich soetwas hier:
1 | if falling_edge(clk) then |
2 | reset_delayed <= reset; |
3 | end if; |
4 | |
5 | if rising_edge(clk) then |
6 | if reset = '1' and reset_delayed = '0' then |
7 | count_q <= 0; |
8 | else |
9 | count_q <= count_q + 1; |
10 | end if; |
11 | end if; |
oder vielleicht auch so:
1 | process(clk) |
2 | if rising_edge(clk) then |
3 | if reset = '1' and reset_delayed = '0' then |
4 | count_q <= 0; |
5 | reset_delayed <= 1; |
6 | else |
7 | count_q <= count_q + 1; |
8 | reset_delayed <= reset; |
9 | end if; |
10 | end if; |
11 | end process; |
:
Bearbeitet durch User
Joe F. schrieb: > Werktätiger schrieb: > (1) if rising_edge(clk) then > (2) reset_delayed <= reset; > (3) if reset = '1' and reset_delayed = '0' then > (4) count_q <= 0; > > Entsteht hier nicht eine Racecondition? > > Die Zuweisung (2) passiert ja quasi gleichzeitig mit dem Vergleich (3), > also würde (4) eigentlich eher selten ausgeführt. Nochmal ansehen, wie sich Signale (erkennbar an <= in Zeile 2) in einem (synchronen) Prozess verhalten ;)
Alright, sorry. Hab wohl zu lange mit Verilog gearbeitet und zugegebenermaßen keine Ahnung von VHDL. In Verilog ist "<=" ein non-blocking assignment, würde also 'gleichzeitig' mit dem if ausgeführt werden. Wer es auch wie ich nicht wusste, hier mehr Infos: http://www.gmvhdl.com/signals.htm
:
Bearbeitet durch User
Joe F. schrieb: > In Verilog ist "<=" ein non-blocking assignment, würde also > 'gleichzeitig' mit dem if ausgeführt werden. Und trotzdem wäre da weit&breit keine Gefahr, weil das Design vollkommen synchron ist. Du hättest schlimmstenfalls einen Takt Latency.
Lothar M. schrieb: > weil das Design vollkommen > synchron ist. Darin liegt ja genau das Problem. 'reset_delayed' würde seinen Zustand ändern, während 'gleichzeitig' der Vergleich mit 'reset' stattfindet (in Verilog). Je nachdem, wie viele ps dazwischen liegen, geht das gut, oder auch nicht. Nicht, dass "asynchron" die Lösung wäre, da weiss man erst recht nicht, wie viel Zeit zwischen den Zustandsänderungen liegt... > Du hättest schlimmstenfalls einen Takt Latency. Was heisst "schlimmstenfalls"? Hat man, oder hat man nicht? Und genau da fängt es an eklig zu werden. Darum ist meiner Meinung nach die beste Lösung 'reset_delayed' zu einem definierten Zeitpunkt (eine halbe Clock vorher) seinen Zustand ändern zu lassen, bevor der Vergleich stattfindet.
:
Bearbeitet durch User
Joe F. schrieb: > 'reset_delayed' würde seinen Zustand ändern, > während 'gleichzeitig' der Vergleich mit 'reset' stattfindet (in > Verilog). > Je nachdem, wie viele ps dazwischen liegen, geht das gut, oder auch > nicht. Weil alle Signale synchron sind (reset und reset_delayed) ändern sich ihre Pegel immer nur nach einer Taktflanke. Dann bricht Hektik aus, denn die Kombinatorik berechnet neue Zustände. Und die müssen nur rechtzeitig zur nächsten Taktflanke stabil sein. Und es ist klar, dass ein synchroner Zähler erst mit der nächsten Taktflanke auf einen Reset reagiert. Das hat mit Verilog oder VHDL nichts zu tun. Hier geht es nur um die Hardware, und die ist beide Male die selbe. Joe F. schrieb: > 'reset_delayed' zu einem definierten Zeitpunkt (eine halbe Clock vorher) > seinen Zustand ändern zu lassen, bevor der Vergleich stattfindet. Auf diese Weise halbiert man sich die zur Verfügung stehende Zeit (bzw man verdoppelt die Taktfrequenz in diesem Pfad) und macht das Timing unnötigerwrise knapper. Konkret ist es so, dass man durch die Verwendung des verzögerten Signals den Reset selbst nicht verzögert, sondern nur einen wiederholten Reset in nächsten Takt verhindert.
:
Bearbeitet durch Moderator
Ich hab mal die Logik skiziert -> da kommt kein delay dazu. Selbst die Gatterlaufzeit durch das AND entschwindet wahrscheinlich in der LUT-Logikwolke die den nächsten Zählerstand ermittelt. Vielleicht wird es sichtbarere wenn man logik und D-FF getrennt beschreibt.
1 | --kombinatorischer process für Logik
|
2 | process(counter_q,reset,reset_delayed_q) |
3 | begin
|
4 | if reset = '1' and reset_delayed_q = '0' then |
5 | counter_next <= 0; |
6 | else
|
7 | counter_next <= counter_q + 1; |
8 | end if; |
9 | end process; |
10 | |
11 | --getakter prozess für FF
|
12 | process(clk) |
13 | begin
|
14 | if rising_edge(clk) then |
15 | reset_delayed_q <= reset; |
16 | counter_q <= counter_next; |
17 | end if; |
18 | end process; |
MfG,
Fpga K. schrieb: > Ich hab mal die Logik skiziert -> da kommt kein delay dazu. Selbst die > Gatterlaufzeit durch das AND entschwindet wahrscheinlich in der > LUT-Logikwolke die den nächsten Zählerstand ermittelt. Ja, denn selbst Uralt-FPGAs bauen auf LUT4 (16Bit LUT) auf, für den Counter wird nur ein LUT-Eingang verwendet, bleiben 2 Eingänge für Reset und Reset-Delay. Damit hat man zum einen nur eine LUT-Stufe (kein Baum) und zum Anderen keine höhere Laufzeit. Nimmt man an, das Reset synchron ist, kommt es durch Delay-Reset bei der Flankenerkennung zu keiner Latenz.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.