Forum: FPGA, VHDL & Co. is_x() in Synthese vs. Simulation


von Fpga I. (fpga-ing)


Lesenswert?

Hallo in die Runde,

ich möchte gerne ein X in der Simulation unterdrücken und den selben 
Code zur Synthese verwenden. Dazu schreibe ich mir ein Modul, welches 
folgende Funktionalität abbildet:
1
-- Simulation:
2
if is_x(DataIn) then
3
  DataOut <= (others => '0');
4
else
5
  DataOut <= DataIn;
6
end if;
7
8
-- Synthese:
9
  DataOut <= DataIn;

Kann ich das Simulationskonstrukt auch in der Synthese verwenden, ohne 
dass zusätzliche Logik generiert wird? Ein X gibt es ja in der Hardware 
nicht.

Alternativ wäre ein If Generate vielleicht eine Option. Wie kann ich für 
die generate Condition erkennen, ob es sich um eine Simulation oder eine 
Synthese handelt?

: Bearbeitet durch User
von Martin S. (strubi)


Lesenswert?

Leider gibt es keine so richtig gut portable Loesung, aber fuer deinen 
Fall ist wohl das `if .. generate` Konstrukt ausreichend, das Setzen der 
entsprechenden Konfig-Variable wiederum toolabhaengig. Sonst weitere 
Optionen, die allerdings auch trotz Standardisierungsbemuehungen nicht 
bei allen Tools gleich funktionieren:

* VHDL configurations
* Pragmas ('-- pragma synthesis_off/on', etc.)

Die generate-Variante duerfte die portabelste sein, solange man keine 
Scherze wie konditionale Einbindung von Modulen bei der 
Lattice-Toolchain ausprobiert.

von Pat A. (patamat)


Lesenswert?

Fpga I. schrieb:
> Wie kann ich für
> die generate Condition erkennen, ob es sich um eine Simulation oder eine
> Synthese handelt?
1
constant simulation: boolean := 
2
    --synthesis translate_off
3
    --pragma translate_off
4
    not
5
    --pragma translate_on
6
    --synthesis translate_on
7
    false;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Fpga I. schrieb:
> Kann ich das Simulationskonstrukt auch in der Synthese verwenden, ohne
> dass zusätzliche Logik generiert wird?
Ich würde das einfach mal selber ausprobieren und mir den RTL-Plan und 
den Ressourcenbedarf ansehen und vergleichen.

Aber ich würde glatt mein Auto drauf wetten, dass der Synthesizer keine 
Hardware dafür erzeugt.

> Ein X gibt es ja in der Hardware nicht.
Ein X gibt es "in der Hardware" schon: das ist eine übliche 
Buskollision, wenn wzei Teilnehmer gleichzeitig schreibend auf einen Bus 
zugreifen und der eine ein low, der andere aber ein high treibt.

Aber wenn die "Hardware" ein FPGA ist, dann gibt es da innen drin nur 
'0' und '1'. Heutige FPGAs haben nicht mal mehr ein 'Z'.

von Pat A. (patamat)


Lesenswert?

Lothar M. schrieb:
> Aber ich würde glatt mein Auto drauf wetten, dass der Synthesizer keine
> Hardware dafür erzeugt.

Da gehe ich mit ;-)

Aber die Frage ist, ob die Synthese das 'X' dann als '0' oder '1' 
ansieht bzw. der Test auf 'X' true oder false ist.

Ich vermute mal letzteres - also false. Aber da es nicht im 
VHDL-Sprachstandard definiert ist, kann jeder Hersteller das handhaben 
wie er will.

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

> Aber die Frage ist, ob die Synthese das 'X' dann als '0' oder '1'
> ansieht bzw. der Test auf 'X' true oder false ist.
>
> Ich vermute mal letzteres - also false.

Eher nicht.
Also angenommen ein Treiber trübe Vcc, ein anderer trübe GND - dann ist 
das Ergebnis Vcc/2, was mit ziemlicher Sicherheit im 
verbotenen/undefinierten Bereich des Signalstandards gehört.

Mal zum Vergleich der TTL-Standard: 
https://de.wikipedia.org/wiki/Logikpegel

Man könnte hier auch einen Exkurs in Richtung Metastabilität folgen 
lassen.
https://de.wikipedia.org/wiki/Metastabilit%C3%A4t_(digitale_Schaltung)

von Pat A. (patamat)


Lesenswert?

Hä?

Wir sind hier bei der Synthese (und Simulation), nicht beim Betrieb 
eines FPGAs und schon gar nicht bei Metastabilität und gegeneinander 
arbeitende Treiber (im FPGA)!

Meine Vermutung, dass die Synthese den Vergleich auf 'X' als false 
ansieht, beruht einfach darauf, dass 'X' immer ungleich '0' und ungleich 
'1' ist ;-)

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Angehängte Dateien:

Lesenswert?

Also nach allgemeinen Verständnis ist gerade die Synthese der Übergang 
von idealisierten zweiwertigen "Richtig"/"Falsch" Denken in die reale 
Welt von (analogen/Kontinuirlichen) Spannungen.

> Meine Vermutung, dass die Synthese den Vergleich auf 'X' als false
> ansieht, beruht einfach darauf

Ich vermute, die Synthese bricht mit Fehlermeldung ab, sobald sie auf 
einen solchen Vergleich im Quelltext trifft.

Halbwegs sinnvoll, wenn auch nicht immer korrekt, wäre noch eine 
Interpretation als "don't care". Siehe Anhang (aus: 
http://www.gstitt.ece.ufl.edu/courses/spring10/eel4712/lectures/vhdl/xst.pdf)

Für Vivado:
https://support.xilinx.com/s/article/64042?language=en_US
-> für vivado synthese vermeide 'X' und 'U' in Vergleichen

: Bearbeitet durch User
von Pat A. (patamat)


Lesenswert?

Bradward B. schrieb:
> Ich vermute, die Synthese bricht mit Fehlermeldung ab, sobald sie auf
> einen solchen Vergleich im Quelltext trifft.

Nein, tut sie nicht - gerade mit Synplify getestet. Warum sollte sie 
auch? 'X' ist immer ungleich '0' oder '1'.

Außerdem ist es zulässig, Konstanten (std_logic) mit 'X', 'Z', 'H', 'L' 
usw. zu definieren und im weiteren Quelltext diese zu vergleichen (und 
entsprechende unterschiedliche Aktionen zu bewirken). Und warum sollte 
das nicht auch bei Signalen möglich sein?


Einzig der Verleich von Was-auch-immer auf '-' (don't care) könnte die 
Synthese sinnvoll als true betrachten.

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

> Einzig der Verleich von Was-auch-immer auf '-' (don't care) könnte die
> Synthese sinnvoll als true betrachten.

Dont care ist mit 'X' und mit '-' assoziiert(siehe Anhang oben). Und 
Dont'care ist weder explizit "true" oder "false". Wobei true and false 
doch eher vom type boolean ist, während 'X' zur neunwertige Logic 
std_logic aka IEEE-1164 gehört.

> Nein, tut sie nicht - gerade mit Synplify getestet

Synplify nist eines von vielen Synthesetools, da gibt es keinen 
herstellerübergreifenden Standard. Schon bei unterschiedlichen 
synthesetargets/Architekturen kann man unterschiedliche Ergebnisse 
erreichen.

: Bearbeitet durch User
von Pat A. (patamat)


Lesenswert?

Bradward B. schrieb:
> Dont care ist aber mit 'X' definiert

Das macht Xilix ganz willkürlich bei XST so.
Ob das Vivado oder Synplify auch so handhaben, steht auf einem ganz 
anderen (Daten-) Blatt.

> Und Dont'care ist weder explizit "true" oder "false"

Habe ich weder geschrieben noch behauptet.

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

Pat A. schrieb:
> Bradward B. schrieb:
>> Dont care ist aber mit 'X' definiert
>
> Das macht Xilix ganz willkürlich bei XST so.
> Ob das Vivado oder Synplify auch so handhaben, steht auf einem ganz
> anderen (Daten-) Blatt.

Auf das "Blatt" von Vivado wurde bereits verwiesen, bei Vivado wird 
empfohlen auf 'X' bei Comperatoren zu verzichten um eben die 
Mehrdeutigkeiten von don't care zu vermeiden.

>> Und Dont'care ist weder explizit "true" oder "false"
>
> Habe ich weder geschrieben noch behauptet.

Naja, da wird ziemlich oft Dont'care in einem Atemzug mit "true" und 
"false" genannt, obwohl "true" und "false" in VHDL zum enum typ boolean 
gehören und "X" und "-" dagegen zum enum type std_logic. Und std_logic 
gehört genau genommen nicht zum selben standard wie VHDL mit boolean 
(IEEE-1076) sondern wurzelt in einem eigenen (IEEE-1164).

von Pat A. (patamat)


Lesenswert?

Bradward B. schrieb:
> Naja, da wird ziemlich oft Dont'care in einem Atemzug mit "true" und
> "false" genannt

Sind meine Sätze zu lang bzw. zu kompliziert für Dich?
Ok, dann mal als Essenz: "Ein Test/Vergleich von ... ergibt true bzw. 
false."

Und sei Dir sicher, 'boolean' und 'std_logic' kann ich gerade so schon 
unterscheiden, obwohl ich VHDL erst seit gestern mache ;-)

So, das wars für mich hier, ich bin dann mal raus. Die Lösung für den TO 
steht schon im 2. und 3. Beitrag.

Noch ein schönes Wochenende!

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

> So, das wars für mich hier, ich bin dann mal raus. Die Lösung für den TO
> steht schon im 2. und 3. Beitrag.

Der 3. Beitrag enthält (Hersteller-) proprietäre Schlüsselworte und ist 
somit als allgemeine Lösung untauglich.

https://insights.sigasi.com/tech/list-known-vhdl-metacomment-pragmas/

Und der zweite Beitrag wiederholt im wesentlich den "workaround" den der 
TO selbst vorgeschlagen hat und verweist im weiteren darauf, das es 
keine allgemeine Lösung gibt.

von Vancouver (vancouver)


Lesenswert?

Mal unabhängig von irgendwelchen Standards und wie sie von den 
Toolherstellern interpretiert werden: Das Codebeispiel des TO hat in der 
Simulation ein anderes Verhalten als in der realen Hardware. Das ist 
schon mal ganz schlechter Style. Ein undefinierter Signalszustand darf 
in einem korrekten Design keinen Einfluss auf das Ergebnis haben, weil 
das sonst indeterministisch wird. Insbesondere kann ein solcher 
X-Zustand nicht verwendet werden, um damit einen Multiplexer zu steuern, 
weil eine digitales Design einfach nicht in der Lage ist, ein X als 
solches zu erkennen.
Es ist daher sinnvoll, is_x() währnd der Synthese grundsätzlich als 
false anzunehmen und wegzuoptimieren, und der Großteil der Tool macht 
das auch so (und gibt zumindest eine Warnung aus).
Aber die saubere Lösung ist, eindeutig zwischen Synthese- und 
Simulationskontext zu unterscheiden, sprich die schon vorgeschlagene 
Lösung mit einem GENERATE-Konstrukt (bzw. ifdef in Verilog). Da die 
Syntesetools dann das is_x() gar nicht zu sehen bekommen, ist die 
Bedeutung des Codes eindeutig- sowohl für die Tools als auch denjenigen, 
der den Code lesen und verstehen muss.
Es gilt auch hier: Eindeutigkeit zum Preis von ein paar mehr Lines of 
Code ist mehr Wert als freakige Shortcuts mit situationsabhängiger 
Semantik. Das steht in der Einleitung von so ziemlich jedem brauchbaren 
Styleguide.

von Rick D. (rickdangerus)


Lesenswert?

Fpga I. schrieb:
> ich möchte gerne ein X in der Simulation unterdrücken und den selben
> Code zur Synthese verwenden.

Ich verwende dafür sowas:
1
   DataOut <= to_01( DataIn);

Die Simulation meckert nicht wegen der 'X'e und in der Synthese wird es 
ignoriert.

von Fpga I. (fpga-ing)


Lesenswert?

Dank Euch für Euren Antworten.

Noch ein kleiner Hintergrund, wie das X zustande kommt:
Es wird immer nur ein Teil eines Blockrams geschrieben und anschließend 
der volle Inhalt de Blockrams versendet (incl. CRC Berechnung über BRAM 
Inhalt). Protokolltechnisch erkennt der Empfänger, wo das Ende der 
genutzten Bytes innerhalb der Nachricht ist, sodass der hintere Teil ein 
"Don't Care" ist. Lediglich die CRC wird über die volle Nachricht 
berechnet. Ist das Blockram nicht initialisiert, liest die Simulation 
ein X zurück, während das FPGA dort typischer Weise eine '0' stehen hat 
(genaueres findet sich im Datenblatt der zugehörigen Bausteinfamilie).
Aufgrund der Verwendung generischer vorhandener Module kann das Blockram 
nicht initialisiert werden (in anderen Kontexten möchte ich das X gerne 
sehen, um in der Simulation gleich darüber zu stolpern, wenn ich zu viel 
aus dem RAM lese).
Damit ich eine CRC sowohl sendeseitig als auch empfangsseitig berechnen 
kann, darf in der Simulation also kein X aus dem Blockram kommen.

Ich habe nun die passenden Lösungsansätze an der Hand und werde noch mal 
kurz in mich gehen und dann eine Variante auswählen. D

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Angehängte Dateien:

Lesenswert?

Fpga I. schrieb:
> Dank Euch für Euren Antworten.
>
> Noch ein kleiner Hintergrund, wie das X zustande kommt:
> Protokolltechnisch erkennt der Empfänger, wo das Ende der
> genutzten Bytes innerhalb der Nachricht ist, sodass der hintere Teil ein
> "Don't Care" ist. Lediglich die CRC wird über die volle Nachricht
> berechnet. Ist das Blockram nicht initialisiert, liest die Simulation
> ein X zurück, während das FPGA dort typischer Weise eine '0' stehen hat
> (genaueres findet sich im Datenblatt der zugehörigen Bausteinfamilie).


Also in Echt würde dort eine '0' stehen aber wegen "suboptimal" 
aufgesetzter Simulation bringt das Model ein 'X' (BTW, ein X steht nicht 
für "don't care" sondern für "Unknown" und bei Unitialisiert wäre 
eigentlich ein 'U' gefordert https://en.wikipedia.org/wiki/IEEE_1164 ) 
???

IMHO ist das die Ursache des Problems an dem man sinnvollerweise eine 
Lösung ansetzen sollte.
Und AFAIK gibt es für jeden BlockRAM eine Möglichkeit der 
Initialisierung, da man diesen BRAM auch als ROM einsetzen könnte. Also 
einfach ein korrektes Model des BRAM benutzen/anfordern, möglicherweise 
liegt es nur an einem suboptimal gesetzten Haken bei der 
Source-Generierung.

Anbei ein Auszug diesbezüglich für die Xilinx series-7 Familie. Wenn 
genannt würde, welche Familie konkret eingesetzt wird, könnte man das 
natürlih auch raussuchen.

von Fpga I. (fpga-ing)


Lesenswert?

Ich beschreibe mein RAM in VHDL. Die Initialisierung des BRam wäre 
technisch problemlos möglich, ist aber nicht gewünscht:
Ich ein generisches Memory Modul, welches mir u.a. ein double buffering 
implementiert. Da das Modul auch in anderen Projekten zum Einsatz kommt, 
möchte ich das BRam nicht initialisieren, da es normalerweise ja ein 
Fehler ist, wenn ich Daten lese, die zuvor nicht geschrieben wurden. In 
sofern hat das X in der Simulation schon seine Berechtigung und soll 
gerne sichtbar bleiben.
Das aktuelle Projekt bildet ist eine Ausnahme, dort ist es ok, Werte zu 
lesen und weiter zu verarbeiten, die nie geschrieben wurden.

Ich habe mir übrigens mit einem Modul beholfen, welches ich hinter die 
BRam ReadData hänge. Es enthält eine einzige Concurrent Anweisung:
   o_DataOut <= to_01(i_DataIn);

P.S.: Ob in der Simulation dort ein X oder U stand, weiß ich nicht mehr, 
vermutlich ein U, aber beides wird ja durch die Funktion is_x() 
abgefangen

: Bearbeitet durch User
von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

Fpga I. schrieb:

> Da das Modul auch in anderen Projekten zum Einsatz kommt,
> möchte ich das BRam nicht initialisieren, da es normalerweise ja ein
> Fehler ist, wenn ich Daten lese, die zuvor nicht geschrieben wurden. In
> sofern hat das X in der Simulation schon seine Berechtigung und soll
> gerne sichtbar bleiben.

Für jedes "Fehler-szenario" sollte man ein eigenen Check im 
Simulationsmodel haben. Hier habe ich den Eindruck, das drei 
verschiedene Szenarien mit dem selben abgedeckt Test werden sollen:

* Speicherfeld ist nicht initialisiert
* Lesen einer Speicherstelle die nicht vorher beschrieben wurde
* mehrer Signalsender treiben gleichzeitig eine Signalleitung.

Das dritte wird IMHO durch ein 'X' angezeigt, ersteres 'U'. Natürlich 
ist es bei der dritten variante wichtig, ob ein Typ mit resolution 
function ('std_logic') oder ohne ('std_ulogic') benutzt.

https://tams.informatik.uni-hamburg.de/applets/hades/webdemos/00-intro/03-stdlogic/resolution.html

Das zweite -read without write- wird durch einen Test im Speicher-modell 
selbst abgefangen, respektive bei der Simulation gabs eine 
warning/report (VHDL-assert) im log.

Der ersten Fall (nicht-initialisierung) könnte/sollte wo nötig 
(Parameter-file/ROM) zu einem Test auf richtige Init-Datensatz erweitert 
sein. Das macht aber auch gerne die Software beim PowerUp-Test selbst, 
sie prüft ob zu Softwareversion passende Parameter-daten vorhanden sind.

: Bearbeitet durch User
von Martin S. (strubi)


Lesenswert?

Bradward B. schrieb:
> * mehrer Signalsender treiben gleichzeitig eine Signalleitung.
>
> Das dritte wird IMHO durch ein 'X' angezeigt, ersteres 'U'. Natürlich
> ist es bei der dritten variante wichtig, ob ein Typ mit resolution
> function ('std_logic') oder ohne ('std_ulogic') benutzt.

Ein 'X' kommt auch z.b. durch arithmetische Operationen von 
uninitialisierten Werten zustande. Mal ganz abgesehen vom RAM-Modell, 
welches auch in gewissen Szenarien ein 'X' aktiv schmeissen koennte.
Da die TDP-Modelle mit ihren unzaehligen Konfigurationsmoeglichkeiten 
einiges an Kombinatorik bereithalten, kommt da schon mal ein 'U' als ein 
'X' raus.

Dann kommen noch Unterschiede zwischen VHDL93 und VHDL08 dazu, die nicht 
ueberall korrekt nach Standard abgefertigt werden. Da zeigte Xsim in der 
Vergangenheit auch mal was anderes an als GHDL.

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
Noch kein Account? Hier anmelden.