Hallo zusammen,
ich habe mir folgendes Programm geschrieben: In Entity 1 werden in einem
Prozess die Signale A_OE und A_CE und-verknüpft. Das Ergebnis
A_Request wird an einen Prozess in Entity 2 geleitet. Dort wird es
ausgewertet und, je nach Ergebnis, der Vektor X_Routing zu "00" oder
"11" gesetzt und zurück an Entity 1 gesendet.
Dort findet nun in einem dritten Prozess die Auswertung statt: Ändert
sich der Vektor von "00" auf "11" oder umgekehrt, soll im späteren
Design eine Reaktion erfolgen. Für's Debugging befülle ich damit aber
ersteinmal nur meine Testvektoren.
Hier meine Beschreibung:
Nur leider funktioniert das Design so nicht. Offenbar hat er Probleme,
über die Grenzen einer Entity hinweg ein kombinatorische Signal zu
leiten. Das Bild im Anhang habe ich mit einem Logikanalysator
aufgenommen. Obwohl der Vektor an den rot markierten Stellen
zweifelsohne von "11" auf "00" wechselt, wird dies nicht erkannt. Die
Abtastfrequenz ist natürlich lang genug (ca. 3x T_Signal)
Warum ist das so? Kann man das über die Entity-Grenzen hinweg kein
kombinatorisches Signal senden? Wenn nein, warum nicht? Sporadisch
funktioniert es ja. Aber warum denn nicht permanent?!
Grüße
Steffen
Steffen Hausinger schrieb:> Kann man das über die Entity-Grenzen hinweg kein> kombinatorisches Signal senden?
Doch, das geht problemlos.
> Warum ist das so?
Sind die beiden Signale A_OE und A_CE asynchron zum FPGA-Takt?
(es sieht so aus, aber leider ist genau der nicht mit im Screenshot)
Dann wundert mich das nicht, du hast ganz einfach ein asynchrones
externes (und dazu noch kombinatorisch verknüpftes) Signal nicht
einsynchronisiert. Und dann wird u.U. der Vergleicher (if X_Routing /=
Last_State then) nicht mehr rechtzeitig fertig. Blöderweise bekommen die
beiden FFs bei der Zuweisung (Last_State := X_Routing) den neuen Zustand
aber offenbar schon mit... :-/
Fazit: du solltest aus diesem Kombinatorikpfad einen Takt komplett
heraushalten, oder aber die Signale standesgemäß einsynchronisieren.
Zum Hintergrund das hier:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Dieses Beispiel passt hier wie die Faust aufs Auge, denn du hast
eigentlich eine Statemachine (Last_State), die nicht richtig reagiert...
Lothar Miller schrieb:> Sind die beiden Signale A_OE und A_CE asynchron zum FPGA-Takt?
Ja, das sind sie. Ich war mir über die Problematik gar nicht bewusst:
Bisher ging ich davon aus, dass die Synchronisation eben in meinem
ersten getakteten Prozess stattfindet. Nur eben nicht über die
Eingangssignale A_OE und A_CE, sondern über X_Routing. Das
kombinatorische Signale X_Routing bleibt aber konstant, so dachte ich.
Was muss ich jetzt machen? A_OE und A_CE über einen getakteten
Prozess einsynchronisieren und zu A_OE_sync und A_CE_sync wandeln?
Es gibt in FPGAs doch diese speziellen(?) "Ausgangs-FF" für synchrone
Ausgangssignale. Gibt es die auch für Eingänge? Wenn ja, wie muss ich es
beschreiben, damit sie verwendet werden? Es geht um einen Spartan 3E.
Grüße
Steffen
Steffen Hausinger schrieb:> Bisher ging ich davon aus, dass die Synchronisation eben in meinem> ersten getakteten Prozess stattfindet.
Da hast du dir selber Sand in die Augen gestreut. Für den Synthesizer
gibt es das Signal "X_Routing" eigentlich gar nicht. Der optimiert sich
da aus seiner internen Wahrheitstabelle selber was zusammen.
> Es gibt in FPGAs doch diese speziellen(?) "Ausgangs-FF" für synchrone> Ausgangssignale. Gibt es die auch für Eingänge?
Nein.
Aber das ist gar nicht dein Problem...
> Was muss ich jetzt machen?
Du mußt
1. die Beschreibung so ändern, dass die Signale eingetaktet werden:
ifX_Routing="00"then-- Wird aktuell Routing "00" angefordert, ...
14
TestVec(0)<='1';-- ...Kanal 0 setzen
15
endif;
16
ifLast_State="00"then-- Wurde bei der letzten Flanke Routing "00" angefordert, ...
17
TestVec(1)<='1';-- ...Kanal 1 setzen
18
endif;
19
ifVery_Last_State/=Last_Statethen-- Wurde das Routing geändert, ...
20
TestVec(2)<='1';-- ...Kanal 2 setzen
21
endif;
22
23
Last_State:=X_Routing;-- Aktuelles Routing für nächste Flanke merken
24
Very_Last_State:=Last_State;
25
26
endif;
27
endprocess;
2. und dann bewerten, ob damit dein Design überhaupt klarkommt.
Denn mit dem Eintakten bekommst du automatisch Latency. Dein TestVec(2)
kommt jetzt einen Takt später.
BTW: Ein Output Enable OE Signal dient idR. zur Umschaltung einer
Busrichtung (Lesen). Das sollte daher direkt auf die Tristatetreiber des
FPGAs gelegt werden. Sonst könntest du dir durch die erwähnte Latency
einen Buskonflikt einhandeln... :-o
Steffen Hausinger schrieb:> Sporadisch> funktioniert es ja. Aber warum denn nicht permanent?!
Solche Aussagen kommen sehr häufig, wenn asynchrone Sachen nicht richtig
behandelt werden :-) (BTDT)
Duke
@Lothar
Würde es sich denn nicht anbieten einfach A_CE und A_OE
einzusynchronisieren. Der Rest der komb. Logik ist dann ja auch
synchron.
Also einfach ein :
signal a_oe_s : std_logic;
signal a_ce_s : std_logic;
process (clk, res)
begin
if rising_edge(clk) then
if res = '1' then
a_oe_s <= '0';
a_ce_s <= '0';
else
a_oe_s <= a_oe;
a_ce_s <= a_ce;
end if;
end if;
end process;
Evtl. noch mit einem weiteren Einsynch-FF pro Leitung.
Müsste doch auch funktionieren oder nicht ?
Rene Böllhoff schrieb:> Müsste doch auch funktionieren oder nicht ?
Ja, das wird es auch tun.
Allerdings würde ich den Reset hier rauslassen, damit nicht unnötig
Routingressourcen verbraucht werden. Und wehe, wenn dieser scheinbar
synchrone Reset hier wieder an einen asynchronen Resettasterpin
angeschlossen ist... ;-)
Nein, Reset habe ich völlig aus meiner Schaltung verbannt. Obwohl ich
eine zeitlang nicht wusste, wie ich dann der Schaltung mitteilen soll,
ab wann der DCM einen sauberen Takt liefert. Ich habe es schließlich mit
der Einstellung "wait until lock goes high" (oder so ähnlich) gelöst.
Ich werde mich dann auch dafür entscheiden, A_OE und A_CE zu
synchronisieren. Dann komme ich auch in anderen Prozessen gar nicht erst
auf die Idee, die unsynchronisierten Varianten zu nehmen.
Lothar Miller schrieb:> BTW: Ein Output Enable OE Signal dient idR. zur Umschaltung einer> Busrichtung (Lesen). Das sollte daher direkt auf die Tristatetreiber des> FPGAs gelegt werden. Sonst könntest du dir durch die erwähnte Latency> einen Buskonflikt einhandeln... :-o
Ich habe das zwar in einer StateMachine gelöst, weil auch noch weitere
(externe) Treiber umgeschaltet werden müssen, aber das interessiert mich
jetzt doch: wie lege ich das Signal direkt auf den Tristatetreiber des
IOB? Macht die Synthese das automatisch, wenn ich etwas schreibe wie
Steffen Hausinger schrieb:> Macht die Synthese das automatisch, wenn ich etwas schreibe wie...
Ja. Aber du mußt hier sinnvollerweise noch ein wenig weiter vorn
anfangen:
Bereits in der Top-Level-Entity muß dieser Bus, der ja ein
bidirektionaler Datenbus vom und zum uC ist, als inout deklariert
werden.
Und dann geht das so (mal von einem low-aktiven OE-Signal ausgegangen):
1
process(A_OE,FPGADataOut)begin
2
ifA_OE='1'then
3
Datenbus_uC<=(others=>'Z');
4
else
5
Datenbus_uC<=FPGADataOut;
6
endif;
7
endprocess;
8
9
FPGADataIn<=Datenbus_uC;
Ich selber schreibe das lieber concurrent (ohne Prozess):
>Und wehe, wenn dieser scheinbar synchrone Reset hier wieder an einen>asynchronen Resettasterpin angeschlossen ist... ;-)
Mist. Ich sollte mich nicht immer angesprochen fühlen bei sowas. Ja ja.
Ich änder meine 500 Prozesse ja schon ab um den Reset ebenfalls synchron
zu machen :-)))
Aber da mal eben eine Offtopic frage zu dem Thema.
Und zwar du meintest das ein Asynchroner Reset u.u auch Probleme mit dem
Routen des Designs geben kann. Ich habe bei meinem Audio-Projekt das
Problem gehabt das ich einen 32x32bit Multiplier in einem Takt verwendet
habe. Das braucht natürlich sehr viele Interconnects. Da die 32Bit sowie
die 64Bit Pfade an mehreren stellen benötigt werden und durch Register
dargestellt werden habe ich auch ein asynchronen Reset. Nun habe ich das
Problem das der Router stellenweise nicht fertig wird weil er 2-6
Leitungen nicht immer Routen kann (congestion on net xyz). Kann ein
Synchroner Reset da vllt auch helfen das Routingproblem zu lösen ? Ich
bin mir da nicht ganz sicher obwohl ich eher denke das das Design durch
den 32x32Bit-Multiplizierer einfach zu vollgestopft ist und der Router
daher nicht fertig wird.
Aber generell würde mich mal interessieren wieviele Ressourcen durch
einen asynchronen Reset mehr verbraten werden als bei einem synchronen.
Gibt es da erfahrungen ? Ist das abhängig von der Anzahl der FF's die
asynchron resettet werden, grob nach dem Motto : pro async FF wird ein
Slice zusätzlich "verschwendet" ?
Ich gebe dir recht das der asynchrone Reset eigentlich Mist ist, aber
bei mir hats soweit immer funktioniert. Was nicht heißt das es gut war,
das weiß ich selbst :)). Aber wieviele Ressourcen weniger würden durch
einen synchronen Reset benötigt werden ? Ich meine das endet dann ja
auch irgendwo in Laufzeit und benutzten Slices/Logik die dann für andere
Dinge wieder frei werden würde/könnte.
Rene Böllhoff schrieb:> Aber generell würde mich mal interessieren wieviele Ressourcen durch> einen asynchronen Reset mehr verbraten werden als bei einem synchronen.> Gibt es da erfahrungen ?
Ich hatte mal die XST-Option async_to_sync ausprobiert. Bei manchen
Designs wurden ein paar Slices eingespaart, bei anderen waren es ein
paar Slices mehr. Das es sich signifikant auf timing/routing ausgewirkt
hätte, kann ich nicht behaupten.
Aber das kann bei anderen Designs natürlich anders aussehen...
Duke
Duke Scarring schrieb:> Das es sich signifikant auf timing/routing ausgewirkt hätte, kann ich> nicht behaupten.
Das hätte eigentlich ich auch erwartet. In einem "normalen" Design
mitteln sich die Vorteile heraus. Es geht eher darum, darüber
nachzudenken, ob überhaupt ein Reset nötig ist...
@Lothar
Die betrachtung in welchen Prozessen ich einen Reset brauche oder nicht
müsste ich auch nochmal für die Designs machen. Ist einfach eine Art
Mechanismus erstmal einen Reset vorzusehen. Meist "rüste" ich den Reset
nach wenn ich in der Simulation sehe das Signale undefiniert sind. Das
ich aber in z.b. einem Multiplizierer mit nachgeschaltetem Register
meist keinen Reset brauche da beim nächsten Takt ja ohnehin ein gültiges
Datenwort (gültige Eingangsworte vorausgesetzt) anliegt, es sei denn ich
hab bei dem Multiplizierer ein Enable, dann könnte (bzw wird) das
Ausgangswort ja undefiniert sein, solange wie nicht einmal ein Enable
gekommen ist. (Hoffe ich konnte das nun richtig erklären :-))