Hi,
ich habe in VHDl eine State Machine mit zwei Prozessen gebaut.
Der erste ist getaktet und schaltet vom alten zum neuen state. Der
andere ist ungetaktet und definiert die Ausgänge im jeweiligen state.
Ich habe jetzt einen idle state, der wartet bis irgendwas passiert. Bis
jetzt war das das Signal von einem Taster. Wenn dieses 1 wurde, ist die
state machine angelaufen. Soweit so gut.
Jetzt möchte ich den Taster ersetzen. Eine andere Komponente schickt
dabei für einen Takt lang (beide Komponenten laufen auf dem gleichen
Takt) einen Impuls. Mit diesem Impuls soll meine state machine starten.
Wenn ich jetzt einfach in meinem idle state
1
ifimpuls='1'then
2
state_neu<=next_state;
3
else
4
state_neu<=idle;
5
endif;
so abfrage, dann kann es ja passieren, dass der neue state nicht
übernommen wird, weil der Impuls nicht während einer steigenden Flanke 1
ist.
Mein Ansatz war jetzt, dass ich in einem extra Prozess die steigende
Flanke des externen Impulses abfrage, damit dann ein Signal setze
(dieses wird dann im idle state auf 1 geprüft) und dieses Signal erst
zurücksetze, wenn meine state machine auch wirklich im nächsten Zustand
ist.
Die Umsetzung bereitet mir allerdings Probleme. Mein grober Plan sieht
so aus:
1
process(rdy)
2
begin
3
ifrising_edge(rdy)then
4
start<='1';
5
elsifstate=w2then
6
start<='0';
7
endif;
8
endprocess;
Allerdings habe ichd ann ein Problem, dass das Signal laut Fehlermeldung
nicht gehalten wird. Eine Zurücksetzung im getakteten Teil der state
machien geht ja auch nicht wegen dem multiple driver Problem.
Kann mir da jemand bitte helfen?
Beste Grüße
Poste mal mehr Code.
Was ist dein Signal rdy? Ist das ein clock? Schau dir mal an, für was
man rising_edge verwenden soll und für was nicht.
Du hast also zwei Prozesse, einen ungetakteten und einen getakteten. Du
schreibst was von Taster.
Ich gehe mal davon aus, dass dein Clock DEUTLICH schneller ist als du
auf den Taster drücken kannst. Dann mach am besten beide Prozesse
synchron zum Takt. Dann wärs doch deutlich einfacher!
Das Signal rdy kommt von meinem FIR Filter. Dieser Filter läuft mit 4MHz
und deshalb ist das rdy signal auch eine Taktperiode des 4MHz Taktes
lang 1. Das Signal rdy widerholt sich mit einer Frequenz von 16kHz.
Die Daten des FIR Filters sollen dann in einem RAM gespeichert werden.
Dafür die State machine.
Das ist mein getakteter Prozess. Er läuft mit der gleichen Frequenz wie
der FIR Filter. cnt ist ein counter, der eine gewisse zeit wartet, bis
er vom init ind en idle Zustand wechselt. in state w5 wird die Adresse
hochgezählt.
1
process(CLKRAM)
2
begin
3
ifrising_edge(CLKRAM)then
4
statealt<=stateneu;
5
6
casestatealtis
7
wheninit=>cnt<=cnt+1;
8
9
whenw5=>addr<=std_logic_vector(unsigned(addr)+1);
10
whenidle=>cnt<=0;
11
12
whenothers=>null;
13
endcase;
14
endif;
15
endprocess;
Das folgende sind dann meine states. Die Zuweisungen sind uninteressant
und deswegen xx <= xx. Wichtig ist state idle, der zu w1 wechselt, wenn
der entprellte Button BTNd(0) gedrückt wird. Das war auch kein Problem,
da man ja länger als 250ns auf den Button drückt und das auch auf jeden
Fall die steigende Flanke von CLKRAM erkennt.
Ich möchte jetzt aber BTNd(0) durch das signal rdy ersetzen, welches nur
250ns lang ist. Wie kann ich sicherstellen, dass es auch vom getakteten
prozess erkannt wird (Periodendauer auch 250ns) und somit mein state
idle zu w1 wechselt?
Tritt tatsächlich ein Problem auf?
Wenn beide Komponenten den gleichen Takt haben, dann sollte das schon
funktionieren.
Die Synthesetools sind ja im Allgemeinen auch nicht dumm.
Hmm ich habe es ehrlich gesagt noch nicht getestet, weil ich davon
ausgegangen bin, dass es dann ab und zu klappt und ab und zu nicht. Je
nachdem ob rdy zur rising edge schon 1 ist oder eben nicht. Wollte da
eigentlich auf Nummer sicher gehen. Oder ist das wirklich ohne Probleme
umsetzbar?
Das Synthesetool sorgt dafür dass alle synchronen Prozesse zur gleichen
Zeit/Taktflanke schalten. Laufzeiten im Chip werden dabei berücksichtigt
und solange das Timing (max. Taktfrequenz <> Laufzeiten) eingehalten
wird sollte es auch funktionieren. Dies bedeutet dass alle Prozesse
gültige Daten "sehen" - du musst daher nicht manuell was dazu beitragen.
Anders sieht es aus wenn asynchrone Eingangssignale direkt in der FSM
abgefragt werden. Dies kann dann sehr wohl zu undefinierten
Zustandsübergängen führen, weshalb man die externen Signale zuerst
einsychronisieren sollte.
Klaus schrieb:> Je nachdem ob rdy zur rising edge schon 1 ist oder eben nicht. Wollte> da eigentlich auf Nummer sicher gehen. Oder ist das wirklich ohne> Probleme umsetzbar?
Das Grundprinzip jedes synchronen Designs ist so: nach einer Taktflanke
herrscht im FPGA große Unruhe. Neue Zählerstände werden berechnet, Logik
ermittelt aktuelle Werte und die Folgezustände von FSM werden berechnet.
Und rechtzeitig vor der nächsten Taktflanke müssen die Werte wieder
stabil sein. Denn dann kommt wieder der Takt und das Spiel geht von
vorne los.
Und deshalb sollte es im Idealfall nur 1 Takt im Sytem geben, und immer
auf die selbe Flanke dieses Taktes reagiert werden.
Wenn rdy mit dem selben Takt erzeugt und ausgewertet wird, dann geht da
nichts schief, wenn du ein Constraint auf den Eingangstakt gesetzt hast.
BTW: wie wird der CLKRAM erzeugt? Und wie viele andere Takte hast du
noch in deinem Design?
Alles klar, das klingt alles sehr logisch und räumt meine Zweifel aus.
Zwischenzeitlich hatte ich , um auf Nummer sicher zu gehen, den Takt
meiner State Machine auf 10Mhz erhöht um auf Nummer sicher zu gehen.
Ich arbeite teilweise schon mit unterschiedlichen Takten. Dazu habe ich
mittels dem Clocking Wizard von Xilinx einen IP Core erstellt und
erzeuge mir aus 100MHz dann 10 und 4 MHz. Sind hier mehrere Takte
wirklich schädlich? Ich hatte eventuell vor noch mehrere Takte zu
implementieren...
alex schrieb:> Chris schrieb:> Sind hier mehrere Takte>> wirklich schädlich? Ich hatte eventuell vor noch mehrere Takte zu>> implementieren...>> Wofür genau?
Ich möchte das System mit mehreren Takten testen und deswegen möchte ich
später einen IP Core haben, der 100, 80, 40, 20, 10 und 4 MHz ausgibt
und ichd ann flexibel wählen kann. Je nach Anwendung würde ich
vielleicht 3 Takte verwenden.
Am Eingang ein System mit dem hohen Takt, dann wird dezimiert(clk des
CIC cores wäre gleich), der FIR Filter läuft dann wohl mit 4 MHz und den
RAM würde ich immer mit 10 MHz betreiben wollen.
Klaus schrieb:> der 100, 80, 40, 20, 10 und 4 MHz ausgibt> und ichd ann flexibel wählen kann.
Dann muß Dein Design mit maximal 100 MHz laufen können. Ich verwende ein
'enable' was mir gültige Daten anzeigt. Wenn die Daten nur mit 10 MHz
anfallen, dann ist das 'enable' auch nur alle 10 Takte mal auf '1'.
Trotzdem brauche ich nur einen Takt im System: den Schnellsten.
Duke