Moin zusammen! Ich arbeite aktuell an einem Zyklischem Register, dass je
nach Zustand einen anderen 8-Bit Wert ausgibt. Bei einer steigenden
Flanke von einem externen TX_Done Signal (ist Taktsynchron kommt nur aus
einem anderem Modul) soll der nächste Zustand getriggert werden und
demnach ein neues Wort an den Ausgang gelegt werden. Ich bin mir aktuell
nicht sicher, ob ich die Defaultwerte korrekt zugewiesen habe. Mein
reset Zustand stellt die Vorraussetzung für den Folgezustand. Das klingt
nicht schlüssig für mich war aber auf den ersten Blick nicht anders
lösbar. Ebenso bin ich mit der Beschreibung meiner Statemachine in
Ein-Prozesslogik nicht zufrieden, da ich Zwei-Prozesslogik gelernt habe.
Die Anforderung war jedoch garantierte Taktsynchronität von daher....
Habt Ihr vielleicht Tips, wie ich die Beschreibung noch Sinnvoller
hinbekomme?
Gruß Ole.
Ole W. schrieb:> Ihr vielleicht Tips, wie ich die Beschreibung noch Sinnvoller> hinbekomme?
Ich würde da statt einer FSM ein RAM/ROM nehmen und mit einem
Indexzähler da durchfahren.
> tx_edge <= Tx_Done and (not tx_reg1);
Diese Flankenerkennerei erscheint mir immer suspekt.
Woher kommt Tx_Done? Warum ist das länger als 1 Tatkzyklus aktiv? Kannst
du das nicht so gestalten, dass das Signal nur 1 Taktzyklus lang
ansteht? Das ist die übliche Vorgehensweise in synchronen Designs.
> if (SRESETN = '1') or (stop = '1')then
Sind das asynchrone Eingänge oder sind die taktsynchron zum clk?
Die SM wollte ich nutzen, da ich entsprechend auf die Verschiedenen
Werte für "Data" in einem anderem Modul auf Antworten erwarte. Darüber
möchte ich also mitschneiden was für eine Antwort ich für die gesendeten
Daten erwarte und dann die Daten in entsprechenden Registern ablegen.
Das State Signal wird später dann ein Ausgang aus der Entity. Es handelt
sich dabei um ein "Zyklisches Ablauf Register" für einen SPI Treiber der
immer wieder die gleichen Daten an N-Slaves verschickt. Ich dachte mir,
dass ich irgendwie sinnvoll mitschneiden musste, zu welchen gesendeten
Daten meine Antworten passen.
Das Tx_Done Signal kommt aus dem SPI-Treiber. Das Auf einen Takt zu
kürzen dürfte kein Problem sein. Wenn ich so darüber nachdenke dann ist
meine Flankenerkennung da tatsächlich eher ein Notbehelf.
Der Reset kommt von Extern über einen Pin, wird jedoch
einsynchronisiert.
Lothar M. schrieb:> Diese Flankenerkennerei erscheint mir immer suspekt.
Warum stört dich das? Flankenerkennung wird doch häufig benötigt. Z.B.
wenn du das Clock-Signal eines I2C (SCL) auswerten willst, das aufgrund
der geringen Frequenz im Design nicht als eigene Clockdomain sondern als
Datensignal behandelt wird. Ein SCL-Zyklus geht dann über viele
Systemtakte, aber interessant ist nur die aktive Flanke des SCL.
@TO:
Warum solltest du bei einer 2-Prozess-Implementierung keine
Taktsynchronität mehr haben? Deine gesamte Logik hängt vom Stateregister
ab, und wenn du das in einen eigenen Prozess packst, ist das ganze
Design immer noch synchron.
Die 2-P-Variante ist auf jeden Fall die saubere Lösung. Im Prozess für
das Zustandregister wertest du nur clk und sreset aus, und alles
andere machst du in einem separaten und rein kombinatorischen Prozess
für den Folgezustand.
Solche Sachen wie
1
if(SRESETN='1')or(stop='1')then
bringen dich mitunter in Teufels Küche, weil du kombinatorische Logik
auf der Reset-Leitung hast. Der Reset soll nur zur Initialisierung des
Designs verwendet werden, und das stop-Signal hat evtl ganz andere
Aufgaben. Die beiden zu verodern ist mindestens "bad practice" bei
manchen Tools und Technologien aber ein dicker Fehler. Zumindest im
ASIC-Design und bei asnychronen Resets. Auch wenn du FPGA machst,
gewöhne dir manche Sachen erst gar nicht an.
Zur den Defaultwerten: Wenn du schon ein Reset-Signal hast, dann
solltest du das auch verwenden, um den Edge-Detektor zu initialisieren,
das erspart dir die Defaults. Und warum setzt du das Stateregister beim
sreset auf "reset", aber auf den Defaultwert "S1"?
Vancouver schrieb:> Flankenerkennung wird doch häufig benötigt. Z.B. wenn du das> Clock-Signal eines I2C (SCL) auswerten willst
Aber eben nicht, wenn Kommunikation zwischen FPGA-internen und
taktsynchronen Modulen stattfindet.
Vancouver schrieb:> Warum solltest du bei einer 2-Prozess-Implementierung keine> Taktsynchronität mehr haben? Deine gesamte Logik hängt vom Stateregister> ab, und wenn du das in einen eigenen Prozess packst, ist das ganze> Design immer noch synchron.
Naja ich habe mir das so erklärt, dass zwar das Zustandsregister
Synchron ist, aber man ja nicht zwingend im Datenpfad ein
Ausgangsregister nach der Übergangslogik hat. Zu dem wird ja dann das
Zustandsregister mit den Übergangsbedingungen zum Zustandswechsel in
einen Prozess gepackt. Das stelle ich mir als Realisierung mit einer MUX
vor + Logik außen rum. Daher meine Annahme, dass das nicht zwingend
Synchron ist.
Vancouver schrieb:> Solche Sachen wieif (SRESETN = '1') or (stop = '1')then> bringen dich mitunter in Teufels Küche, weil du kombinatorische Logik> auf der Reset-Leitung hast. Der Reset soll nur zur Initialisierung des> Designs verwendet werden, und das stop-Signal hat evtl ganz andere> Aufgaben. Die beiden zu verodern ist mindestens "bad practice"
Also nehme ich besser das Stop Signal dort raus und dann handelt es sich
wieder um einen Synchronen Reset?
Vancouver schrieb:> Und warum setzt du das Stateregister beim> sreset auf "reset", aber auf den Defaultwert "S1"?
Das kommt daher, da S1 ja erst Aktiv wird wenn der Prozess verlassen
wird. Im nächsten Zyklus nach dem Reset hätte ich immer gerne S1 als
Startbedingung, (Und in S1 dann S2 als Folgezustand, S2 -> S3 usw.)
Damit die Zustände "nacheinander" abgearbeitet werden.
Bin mir nicht sicher ob das das richtige vorgehen ist, aber das war so
nach meinem ASM Chart das beste was mir eingefallen ist
Ole W. schrieb:> Naja ich habe mir das so erklärt, dass zwar das Zustandsregister> Synchron ist, aber man ja nicht zwingend im Datenpfad ein> Ausgangsregister nach der Übergangslogik hat.
Das Zustandregister ist das Ausgangsregister der Übergangslogik. Die
Eingänge werden zusammen mit dem aktuellen Zustandsregister in die
Übergangslogik gesteckt, und deren Ergebnis landet im nächsten Takt
wieder im Zustandsregister. Der Wert am Data-Ausgang hängt nur vom
Zustand ab und vom Edge-Detektor, die sind beide synchron, damit ist
Data auch synchron.
Ich vermute du meinst die Gatterlaufzeit der Übergangs- und
Ausgangsfunktion. Die ist natürlich vorhanden, aber solange die kürzer
ist als eine Taktperiode minus Setup-Zeit der Flops, hat sie keinen
Effekt. Ob das der Fall ist, sagt dir der Timing-Analyzer deiner
Toolchain.
Asynchron wirst du nur, wenn ein asynchroner Eingang deiner Schaltung
kombinatorisch auf einen Ausgang wirkt, aber das ist hier nicht der
Fall.
Ole W. schrieb:> Also nehme ich besser das Stop Signal dort raus und dann handelt es sich> wieder um einen Synchronen Reset?
Wie gesagt, schreib einen getakteten Prozess der nur clk und sreset
auswertet, und stop verwendest du im Zustandsübergangsprozess. stop wird
damit Teil der Übergangsfunktion, und sreset ist der Reset. Dann
schaffst du klare Verhältnisse.
Du brauchst bei der 2-P-Struktur natürlich noch ein next_state-Signal,
das den Eingang des Stateregisters bildet. Ein vorbildlich
implementiertes Beispiel findest du hier:
https://vhdlguru.blogspot.com/2010/04/how-to-implement-state-machines-in-vhdl.html
nur dass dort ein asynchroner Reset verwendet wird.
Ole W. schrieb:> Das kommt daher, da S1 ja erst Aktiv wird wenn der Prozess verlassen> wird.
Du möchtest also, dass die FSM im Zustand S1 ist, während der sresetn
aktiv ist?
Ole W. schrieb:> Im nächsten Zyklus nach dem Reset hätte ich immer gerne S1 als> Startbedingung,
Warum schreibst du dann
Ole W. schrieb:> Ebenso bin ich mit der Beschreibung meiner Statemachine in> Ein-Prozesslogik nicht zufrieden, da ich Zwei-Prozesslogik gelernt habe.
Die Argumentation ist ehrlich gesagt eher schlecht nachzuvollziehen. Was
ist das Problem jenseits dieser "Unzufriedenheit"?
Ole W. schrieb:> Der Reset kommt von Extern über einen Pin, wird jedoch einsynchronisiert.
Wie oft kommt der? Nur 1x beim Einschalten? Oder sogar noch von einem
Resetknopf (und wenn ja: wer drückt den wie oft)? Oder wid der Reset
sogar nur für die Entwicklung "gebraucht"?
Dann nutze den üblichen "Lade- und Konfugurationsmechanismus" des FPGAs.
Das führt dann zum Schluss dieses Initialisierungsprozesses sowieso
einen Reset auf die definierten Zustände aus. Und du musst nicht
"Reset-Code" verwalten, der sowieso irrelevant ist und dir eh' nur
unnötige Sorgen macht.
Mein Code würde etwa so aussehen:
1
:
2
:
3
processbegin
4
waituntilrising_edge(CLK);
5
ifSRESETN='1'orstop='1'then
6
Data<=x"0A";-- hier fehlt mir jeweils noch irgendwie der 'Tx_Start'
7
State<=S1;
8
else
9
caseStateis
10
whenS1=>ifTx_Done='1'then
11
Data<=x"0B";
12
State<=S2;
13
endif;
14
-- kein else, denn wenn ich nicht weiterschalte, dann
15
-- bleibt die FSM einfach beim jeweils aktuellen Zustand
16
17
whenS2=>ifTx_Done='1'then
18
Data<=x"0C";
19
State<=S3;
20
endif;
21
22
whenS3=>ifTx_Done='1'then
23
Data<=x"0A";
24
State<=S1;
25
endif;
26
endcase;
27
endif;
28
endprocess;
29
:
30
:
Und wenn man sich das nochmal anschaut, dann könnte man sogar auf so
eine Idee kommen:
1
:
2
:
3
processbegin
4
waituntilrising_edge(CLK);
5
ifSRESETN='1'orstop='1'then
6
Data<=x"0A";
7
State<=S1;
8
else
9
ifTx_Done='1'then-- die Tx_Done Abfrage "nach vorne rausziehen"
Ole W. schrieb:> Naja ich habe mir das so erklärt, dass zwar das Zustandsregister> Synchron ist, aber man ja nicht zwingend im Datenpfad ein> Ausgangsregister nach der Übergangslogik hat.
Ob du ein Register nach der Überganslogik für deinen Ausgang hast oder
nicht, das beschreibst du ja in deinem Code.
Und du kannst beide Varianten sowohl mit in einem oder zwei Prozessen
beschreiben (oder in noch viel verwirrenderen Schreibstilen).
Ein Stil mit zwei Prozessen und passenden Namensregeln (z. B. einen
Record für alle Register), kann es vereinfachen zu sehen, dass da
jememand einen Ausgang direkt treibt und sich fragen, ob das so gedacht
war oder nicht.
Lothar M. schrieb:> Die Argumentation ist ehrlich gesagt eher schlecht nachzuvollziehen. Was> ist das Problem jenseits dieser "Unzufriedenheit"?
Nunja unzufrieden war evt. das falsche Wort. Es ist in meiner Firma so
üblich alles in ein Prozess-Logik zu schreiben. Daher kam mein
Gedankengang.
Lothar M. schrieb:> Wie oft kommt der? Nur 1x beim Einschalten? Oder sogar noch von einem> Resetknopf (und wenn ja: wer drückt den wie oft)? Oder wid der Reset> sogar nur für die Entwicklung "gebraucht"?
Der kommt meines Wissens nach von einer externen CPU und wird dann
Softwareseitig gesteuert. Über das "wann" habe ich keine Kontrolle, ich
muss es eben nur abfangen.
Vancouver schrieb:> Warum schreibst du dann
Gute Frage, je länge ich da rauf schaue, desto mehr Frage ich mich das
auch.
Christoph Z. schrieb:> Ein Stil mit zwei Prozessen und passenden Namensregeln (z. B. einen> Record für alle Register), kann es vereinfachen zu sehen, dass da> jememand einen Ausgang direkt treibt und sich fragen, ob das so gedacht> war oder nicht.
Das ist ein sehr guter Punkt. Danke dafür!