Moin,
gleich voran - das ist keine Frage sondern ein Erfahrungsbericht.
Ich arbeite z.Z an einen Evalboard mit Spartan-6 und Speicher, fürs
erste nutze ich den Speicher nicht und schalte deshalb den Datenbus im
FPGA hochohmig damit die beiden IC's nicht versehentlich gegeneinander
treiben.
(Boardbeschreibung: http://www.ztex.de/usb-fpga-1/usb-fpga-1.11.d.html )
Dazu in der Port - Liste eine Initialisierung mit 'Z':
Leider ohne gewünschtes Ergebniss, der FPGA wird verdächtig heiss
(Finger unangenehm heiss, gemessen 51°C). Der FPGA ist zu einem prozent
ausgelastet.
Die Lösung brachte erst die händische Instanzierung der Pads:
Danach blieb der FPGA auf gefühlt leicht über Raumtemperatur.
Benutzt hab ich ISE 14.7 und XST.
Das Ergebniss hat mich etwas überrascht da ich aonst mit Z-Zuweisung
gute Erfahrung gemacht habe. Vielleicht liegst an irgendwelchen
Tooleinstellungen (Syntheseoptionen, map-optionen), vielleicht hätte es
über den "Umweg" Signalzuweisung und dieses auf 'Z' funktioniert. Der
sicherste Weg scheint aber die direkte Instanziierung zu sein.
MfG,
Fpga K. schrieb:> Dazu in der Port - Liste eine Initialisierung mit 'Z':> mcb3_dram_dq : inout std_logic_vector(15 downto 0):= (others =>> 'Z');
Du setzt das Signal bzw. Vektor in der Portliste
(nehme mal an, Du überschreibst das nicht in der
Implementierung).
Statt dessen setze ich immer den Vektor bzw. das
einzelne Signal immer in der Implementierung, hat
bis jetzt immer geklappt (Xilinx/Altera/Lattice).
Falls Du einen Testpin zur Verfügung hast: Setze
den doch mal in der Portliste auf 'Z' und teste
mit einem Pushbutton+Pullup+Pulldown und DSO, ob
wirklich 'Z' vorliegt.
In der Portliste bringt das nix. Das muss explizit nochmal gesetzt
werden. Dann reicht aber ein
1
mcb3_dram_dq<=(others=>'Z');
Wenn ich in der Portliste := '0' angebe, wird ja auch kein Kurzschluss
nach GND und auch kein Pull-Down am Eingang gebaut. Das ist für die
Simulation hilfreich, aber bei der Implementierung bringt es nichts.
Jedenfalls bei Xilinx.
Was da letztlich anliegt, bestimmen mitunter auch die
Syntheseeinstellungen, wenn die PINs verschwinden. Das kann durchaus
passieren, wenn man den Ausgang auf Z setzt, weil das design innen drin
nicht dranhängt, damit Teile wegfallen und andere Pins weg sind. Wenn
dann die Implementierung da einen pull oder gar GND draufschaltet, wird
es ungemütlich.
Zudem ist das nicht zielführen, Ausgänge einfach auf Z zu setzen, weil
die Leitungen im anderen unbeschalteten Fall floaten und den Chip
triggern.
WENN WAS AM FPGA ANGESCHLOSSEN IST, MUSS ES AUCH SAUBER BEDIENT WERDEN.
Sorry, aber das ist Quatsch! 'Z' ist ein definierter Zustand für einen
Ausgang, ist doch völlig normal, einen Open-Drain zu haben. Ob der nun
immer auf Z ist oder irgendwie gesteuert wird, ist unerheblich. Das ist
genauso sauber wie 0 oder 1. Kein Synthese/Implement-Tool ersetzt
einfach meine explizite <= 'Z' Zuweisung durch was anderes. Für
unbenutzte Pins, die überhaupt nicht in der Entity auftauchen, kann man
extra noch einstellen, wie sie sich verhalten.
Ob ich einen Port (hier beim TO ein inout, kein out) eine '0', '1' oder
'Z' zuweise ist schon ein Großer Unterschied. Es gibt keine internen
hochohmig im FPGA den man irgendwie ans Pad schalten. Sondern es wird
tatsächlich im Pad der Treiber umgeschaltet. Die '1' oder '0' dagegen
wird tatsächlich an das PAD "durchgeschaltet".
Deshalb finde ich auch eine Signalzuweisung mit 'Z' unlogisch - 'Z' ist
kein Zustand eines FPGA-internen Signals.
(Einschub: bis Spartan2E könnte man zwar auch internen Busse mit 'Z'
beschreiben, aber das ist durch das Synthese-tool immer auf Multiplexer
umgeformt worden, da es intern keine Tristatetreiber gibt.)
Was aber egal ist, wenn die Synthese eben verlangt das man den Treiber
durch Signalzuweisen abschalten muss, dann ist das eben so. Aber dann
versteh ich nicht wass an der Zuweisung bei der Port-deklaration anders
ist. Einige hab ich dort mit '0' resp '1' zugewiesen, was wunderbar
funktionierte - nur 'Z' eben nicht.
Mit einem Blick auf die Verschaltung einer IO-Zelle wird es vielleicht
klarer:
https://www.mikrocontroller.net/attachment/204187/s6_iopad.png
-> Das Signal ('1'/'0') wird über den Eingang '0' durchgeschaltet, das
hochohmig schalten des Treibers ('Z') ist über einen weiterern Eingang
('T) realisiert. Aber nicht über einen einzigen Port-Input wie die
VHDL-Beschreibung pad_out <= 'Z'; vermuten lässt.
Die VHDL-korrekte Modellierung für das PAD-Ausgang abschalten wäre
dementsprechend auch das "null" statement. Hab ich aber nie ausprobiert.
Vielleicht spiel ich heut am Feiertag weiter mit dem Design rum um alle
Möglichkeiten rauszufinden wie man nun deklarierte Ports sicher
hochohmig schalten kann.
MfG,
FPGA-Polizei schrieb im Beitrag #4591406:
> Was da letztlich anliegt, bestimmen mitunter auch die> Syntheseeinstellungen, wenn die PINs verschwinden.
Die Pins "verwschwinden" hier nicht, die Syntheseeinstellung "Add
IO-Buffers" hab ich auch im Verdacht aber nicht genauer ausprobiert. Ist
hier aber auch aktiviert.
> Zudem ist das nicht zielführen, Ausgänge einfach auf Z zu setzen, weil> die Leitungen im anderen unbeschalteten Fall floaten und den Chip> triggern.>> WENN WAS AM FPGA ANGESCHLOSSEN IST, MUSS ES AUCH SAUBER BEDIENT WERDEN.
Einen Bus der dafür ausgelegt ist auf hochohmig geschaltet zu werden
(wie der hier angeführte SDRAM-Databus) durch Schalten der jeweiligen
FPGA-Pins auf 'Z' hochohmig zu schalten, ist "sauber bedient". - Daran
ändert auch die POLIZEI nichts.
MfG,
Fpga K. schrieb:> Vielleicht spiel ich heut am Feiertag weiter mit dem Design rum um alle> Möglichkeiten rauszufinden wie man nun deklarierte Ports sicher> hochohmig schalten kann.
Dann schau vielleicht mal nach, ob bei deiner "Heizvariante" eventuell
die input termination aktiv blieb (weil es z.B. inmcontraintsfile noch
eine entsprechende Einstellung gab). In irgendeinem Report
(wahrscheinlich Mapper) sollte das stehen.
Wenn die Split Termination aktiv ist, verbrät der IO auch im High-Z
ordentlich Leistung.
Achim S. schrieb:> Wenn die Split Termination aktiv ist, verbrät der IO auch im High-Z> ordentlich Leistung.
Ups: ich sollte nicht schreiben "auch im High-Z" sondern "nur im
High-Z": sobald der IO auf Ausgang geschaltet wird, wird die
Terminierung deaktiviert und der Leistungsverbrauch sinkt (S. 17 im
UG381)
Fpga K. schrieb:> Deshalb finde ich auch eine Signalzuweisung mit 'Z' unlogisch - 'Z' ist> kein Zustand eines FPGA-internen Signals.
Intern ist das natürlich nicht erlaubt. Klar, aber wenn du den Port
explizit auf 'Z' setzt ist das natürlich vollkommen logisch und legitim,
was anderes würdest du doch bei einem Speicher auch nicht machen. Beim
Lesen Z und beim Schreiben halt treiben. In dem o.g. Fall ist es ja
keine Zuweisung an ein Signal, sondern direkt an einen Port.
So hab mal ein bißchen mit FPGA_editor und Codevarianten rumgespielt.
Im .ucf wird für das beschriebene Pin eine Terminierung aktiviert:
NET "mcb3_dram_dq[*]" IN_TERM =UNTUNED_SPLIT_50;
Das ucf-file hab ich so vom Evalboardhersteller übernohmen.
Bei der Heizvarianten (port mit 'Z' als default) wird das IOB wie im
Anhang allokiert, also mit Split_Termination und als Eingang.
Bei den gesuchten Nicht-Heizvarianten (Instanziierung; Umweg
Signalzuweisung) wird das IOB nicht genutzt und wird daher im
FPGA-Editor als unbenutzt angezeigt. Im mapper findet sich die Message
"WARNING:MapLib:701 - Signal mcb3_dram_dq<0> connected to top level port
mcb3_dram_dq<0> has been removed."
Das überraschte mich jetzt in verschiedenen Aspekten:
-obwohl als hochohmig beschrieben treibt das Pad und entspricht genau
dem Tipp von Achim ein paar Posts vorher (Danke!)
-wird das IOB in der beschriebenen Weise instanziiert (Input zu FPGA
offen; Tristatetreiber immer aktiv (Output also hohohmig) wird es
komplett entfernt. Erwartet hatte ich, das es gerade nicht entfernt
wird, wenn es instanziiert ist.
Es kann also bei der "Deaktivierung" von beschriebenen Ports zu Fehlern
kommen. Besser wäre nichtbenutzte Pins nicht in die Portliste der
Top-entity aufzunehmen. Zusätzlich muß aber im Workflow bei generate
Programming file -> Unterpunkt Configuration Options für alle
UnusedIOPins "Float" ausgewählt sein.
Dank für die Hinweise, wieder was gelernt.
MfG,
Fpga K. schrieb:> Zusätzlich muß aber im Workflow bei generate Programming file ->> Unterpunkt Configuration Options für alle UnusedIOPins "Float"> ausgewählt sein.
Najaaa, das ist aber genauso gefährlich denn floatende FPGA Eingänge
können auch massiv Strom ziehen, dann schon lieber auf PullUp stellen.
Bei CPLDs von Xilinx konnte man mit flotenden Eingängen richtig dolle
Heizungen bauen, bei den FPGAs ist es etwas besser, aber ohne externe
Pull Widerstände sollte man das nicht machen.
Fpga K. schrieb:> Es kann also bei der "Deaktivierung" von beschriebenen Ports zu Fehlern> kommen. Besser wäre nichtbenutzte Pins nicht in die Portliste der> Top-entity aufzunehmen. Zusätzlich muß aber im Workflow bei generate> Programming file -> Unterpunkt Configuration Options für alle> UnusedIOPins "Float" ausgewählt sein.
Eingänge bei CMOS floaten zu lassen ist eigentlich nie eine gute Idee.
Eingekoppelte Signale von benachbarten Pins oder Pegel im verbotenen
Bereich zwischen L und H können für höhere Stromaufnahme sorgen.
Es wäre besser bei unbenutzten Pins die Pullups (oder Pulldowns) zu
aktivieren.
Christian R. schrieb:> Najaaa, das ist aber genauso gefährlich denn floatende FPGA Eingänge> können auch massiv Strom ziehen, dann schon lieber auf PullUp stellen.
oder gleich auf "Keeper": wenn doch mal was von außen dagegen treiben
sollte, spart man sich so sogar den Pullup-Strom.
Fpga K. schrieb:> -obwohl als hochohmig beschrieben treibt das Pad
na ja, formal betrachtet treibt das Pad nicht sondern terminiert ein
Signal, dass ggf. von außen getrieben wird. Für die Verlustleistung
nützt diese feine Unterscheidung aber halt nichts: jede 50Ohm
Split-Termination zieht mit 200Ohm an der 1,5V Versorgung (auch wenn von
außen nichts getrieben wird). Und da 16 DQ-pins plus 4 DQS-pins (2
differentiell) parallel liegen, läppert sich das.
Fpga K. schrieb:> Es kann also bei der "Deaktivierung" von beschriebenen Ports zu Fehlern> kommen.
Möglicherweise ist es ein Unterschied, ob die temporär oder permanent
auf Z gestellt werden und was die Synthese meint, da vereinfachen zu
können. Es darf aber in keinem Fall sein, dass ein Port getrieben wird,
wenn er auf Z steht, weil dann der Input Buffer aktiv sein muss. Interne
Signal sollte man da tunlichst vermeiden. Besonders in VHDL ist es nicht
wirklich möglich, ein Signal bis hin zum echten Pin sauber als
bidirektional, buffer oder als Z zu treiben, weil das Signal VOR dem
buffer eben gar nicht z ist, sondern es die Implementierung nach
dahinter verschieben muss.
Die Benutzung von Z als Ausgang ist ja auch nur ein halbfauler
Konstrukt, der so in der Realität nicht (mehr) existiert, weil die Pins
in den meisten FPGAs heute beides sind, IN und OUT! Damit müsste man
sich streng genommen von der Methodik verabschieden, einen Port zu
schreiben und mit einem anderen Signal zu lesen.
Wenn man das tut, sollte man die Mimik immer extra und ausdrücklich als
enable Buffer-Konstrukt mit einem ausdrücklichen enable formulieren. Ich
empfehle dazu, immer einen physischen wrapper des Logikdesigns, welches
das Buf-Enable ausdrücklich rausführt. In der Simulation kann man dann
das Logikdesign prima gegen ein Model arbeiten und die Signale treiben
lassen, damit sie herrlisch kollidieren, oder man formuliert - wie ich
es tue - in der Testbench einen solchen Tristatebuffer, damit man sieht,
dass und wann es korrekt arbeitet.
Wenn man das so formuliert, sollte die Synthese den Tristatebuffer
erkennen und einbauen.
Normalerweise geht das auch, allerdings fällt mir ein Fall ein, wo ich
bei einem Altera Cyclone einen Reset zu einem DSP hin passiv nicht
treiben und auch nicht einaml auf Z setzen durfte, obwohl er physisch am
DSP gepullt war, weil er trotzdem irgendwie kam! - Wieso auch immer!
Ich musste den Port dann ausdrücklich auf Input stellen.
Bei mir läuft sowas unter tool-Fehler!
> Besser wäre nichtbenutzte Pins nicht in die Portliste der> Top-entity aufzunehmen.
Das widerstrebt mir z.B. weil der FPGA ja real angeschlossen ist und dem
Pin mitgeteilt werden sollte, wie er sich zu verhalten hat. Gfs ist es
aber nicht ratsam, das im VHDL zu machen sondern per Constraint der
Implementierung mit auf den Weg zu geben.
> Zusätzlich muß aber im Workflow bei generate> Programming file -> Unterpunkt Configuration Options für alle> UnusedIOPins "Float" ausgewählt sein.
Das ist der Fallstrick Nummer 1 bei FPGAs. Ich errinnere an die Xilinx
ISE, die irgendwann mal mit einem Defaultwert "GND" daher kam und
etliche Designs nicht mehr funktionierten, weil zuvor immer High
angegeben war und der Programmierer sich nicht drum gekümmert hatte.
Man sollte nach meinem Emfinden IMMER ALLE Ports definieren, die
angeschlossen sind und die dann so beschalten, wie nötig. Nur die , die
wirklich nicht angeschlossen sind, werden per default gesteuert und zwar
als Ausgänge mit Z. Wenn man sie als Inputs nimmt, dann brauchen sie
einen pulldown, weil sie sonst floaten, und das kostet wieder etwas
Strom.
Es gibt nur einen Fall, wo ich davon abweichen würde:
Bei schnellen Schaltungen, die ein SSO-Problem bekommen könnten, ist es
mithunter hilfreich, dem FPGA weitere GNDs zu verpassen, indem man alle
nichtbenötigten Pins im letzten PCB-Lauf physikalisch auf GND legt und
sie dann im design passend als Ausgang mit 0 definiert. Damit wird eine
faktische Verbindung zum GND geschaffen, die hilft, den internen (etwas)
zu stabilisieren. Praktisch liegt da eine 30 Ohm-Brücke für geringe
Ströme und eine geringe Kapazität. Kostet zwar auch Strom - allerdings
den, den man wegen sauberer Pegel haben will.
Wenn das mit dem Z tatsächlich nicht funktioniert, muss man eben einen
echten Tristatebuffer als Primitive einsetzen und auf die bequeme
Formulierung mit Z verzichten.
Jürgen S. schrieb:> Es darf aber in keinem Fall sein, dass ein Port getrieben wird,> wenn er auf Z steht, weil dann der Input Buffer aktiv sein muss.
Hier wird kein Port getrieben: das Design funktioniert, der IO steht auf
Z und ist in diesem Moment ein echter Eingang (auch wenn sein Signal für
nichts verwendet wird). Aber er ist kein hochohmiger Eingang sondern
ein niederohmiger mit einer Signalterminierung von ~50Ohm (um
Reflexionen von externen Signalen zu vermeiden, wie sie an hochohmigen
Eingängen entstehen).
Die Terminierung ist deshalb aktiv, weil das explizit im ucf angegeben
war. Deswegen "sieht es so aus" als würde der IO einen Midlevel treiben.
In Wirklichkeit treibt er aber kein Ausgangssignal sondern er schließt
die Leitung effektiv mit ~50Ohm gegen Midlevel ab. Und die Realisierung
der Terminierung per Split-Termination sorgt für einen dauernden Strom
von VCCIO nach GND, der die beobachtete "Heizung" erklärt.
Bei einem reinen input würde das genau so aussehen wie bei diesem IO -
die Terminierungsangabe im ucf entscheidet darüber, ob der Input
hochohmig ist oder niederohmig und ob dauerhaft Strom durch die
Terminierungswiderstände (im Innern des FPGA) fließt.
Jetzt es aber etwas durcheinander: Entweder ich nutze den Port (nur) als
Eingang oder als Ein-Ausgang mit Z (oder auch nicht). Laut TE ist es ein
Ausgang, der (temporär) mit Z getrieben wird. D.h. der output buffer ist
teilweise disabled oder aber eben auch nicht. Soweit ok.
Aber das Problem war doch offenbar ein ungewolltes Terminieren?
>Die Terminierung ist deshalb aktiv, weil das explizit im ucf angegeben
war.
Wurde da eine output termination kommandiert?
P.S. Ein Terminieren ist durchaus ein Treiben! (Aus FPGA-Funktionssicht
vielleicht nicht, aber physikalisch sehr wohl).
Jürgen S. schrieb:> Jetzt es aber etwas durcheinander
Wenn man den ganzen Thread liest nicht. Der Ausgang wurde dauerhaft auf
Z gesetzt, und Grund für das Heizen war, dass im ucf noch eine
Terminierung vom Hersteller des boards aktiv.
Jürgen S. schrieb:> Wurde da eine output termination kommandiert?
eine input-Terminierung (deshalb heizt sie ja auch, wenn der IO auf Z
steht):
Fpga K. schrieb:> Im .ucf wird für das beschriebene Pin eine Terminierung aktiviert:> NET "mcb3_dram_dq[*]" IN_TERM =UNTUNED_SPLIT_50;Jürgen S. schrieb:> P.S. Ein Terminieren ist durchaus ein Treiben!
wenn du das so nennen willst: gerne. Aber dann bist du nicht ganz
konsistent in deinen Bezeichnungen. Denn an anderer Stelle liest sich
dein Beitrag so, als würden Treiben und Nutzen des Input-Buffers sich
gegenseitig ausschließen.
Jürgen S. schrieb:> Es darf aber in keinem Fall sein, dass ein Port getrieben wird,> wenn er auf Z steht, weil dann der Input Buffer aktiv sein muss.
Also: dieser Pin ist inout, er steht dauerhaft auf Input (Z), und er
wird terminiert. Ob du das nun Treiben nennen willst oder nicht,
überlasse ich dir.
Jürgen S. schrieb:> Jetzt es aber etwas durcheinander: Entweder ich nutze den Port (nur) als> Eingang oder als Ein-Ausgang mit Z (oder auch nicht). Laut TE ist es ein> Ausgang, der (temporär) mit Z getrieben wird. D.h. der output buffer ist> teilweise disabled oder aber eben auch nicht. Soweit ok.
Während des Threads wurde meine Anfangshypothese von "misslungen
hochohnig Konfigurieren" widerlegt, das ist wohl Ursache des
Durcheinanders.
Das Problem machte sich durch eine übermäßiges Erhitzung des FPGA's
bemerkbar, etwas was ich mit meiner inzwischen etwas angegrauten
Erfahrung als Gegeneinandertreiben zwischen FPGA-Ausgang uns Ausgängen
andere IC's auf dem board (fehl-) interpretierte.
Also setzte ich als (vermeintliche) Lösung des Hitzeproblems auf
permanentas hochohmig Schalten eines EinAusgang-port (siehe
codeschnipsel Eingangspost)
> Aber das Problem war doch offenbar ein ungewolltes Terminieren?>>>Die Terminierung ist deshalb aktiv, weil das explizit im ucf angegeben> war.>> Wurde da eine output termination kommandiert?
Es wurde eine Input-Terminierung kommandiert
1
NET "mcb3_dram_dq[*]" IN_TERM =UNTUNED_SPLIT_50;
und in der zuerst geschilderten Variante wird das Pad nicht vollständig
wegoptimiert sondern bleibt als Eingang erhalten. Deshalb blieb auf die
Eingangsterminierung aktiv, die für die Erhitzung verantwortlich ist. In
den anderen Varianten wird das Pas als komplett unbenutzt erkannt und
damit samt der Eingangs-terminierung wegoptimiert.
Die Problem-ursache hier ist also die Terminierung. Die wird auch bei
einigen Varianten der Beschreibung als permanent hochohmig deaktiviert,
was ich ebenfalls in die Richtung "Problem ist hochohmig schalten"
fehlinterpretierte.
Wäre mir bewußt gewesen, das es überhaupt eine Input-Terminierung gibt,
wie sich diese auswirkt und das sie in diesem Design aktiv ist, wäre es
zu den Fehldeutungen nicht gekommen - man lernt halt nie aus.
http://www.xilinx.com/support/documentation/user_guides/ug381.pdf -S. 17
"Spartan-6 FPGA I/Os contain optional on-chip input termination
resistors that can reduce the need for external resistors. ... The
structure is that of a pull-up and pull-down resistor in parallel,
providing a Thevenin-equivalent termination resistance to a VCCO/2
level. ...
The input termination resistors will always be present whenever the I/O
is 3-stated, and instantly turned off when the output buffer is
enabled."
MfG,
Fpga K. schrieb:> Wäre mir bewußt gewesen, das es überhaupt eine Input-Terminierung gibt,
Genau das war der Hintergrund meiner Frage.
Wie gesagt, plädiere ich immer dafür, die Physik nicht im VHDL sondern
extern / drumherum zu gestalten. Bei den UCFs kann man sich überlegen,
ob man das trennt, also Synthese- und Impl. contraints. Wo es
interessant wird, sind nämlich solche netten Fälle, wie 16 Bit Busse,
bei denen manche Leitungen nicht verwendet werden, physisch aber
verdrahtet sind.
Ich verwalte meine IOs gerne in meinem Excel, dass ich aus dem erst
gewonnenen IO report erzeuge. Darin wird alles eingetragen, inklusive
der Terminierungen, der Pulls, aber auch externe Pulls von der
Schaltung.
Dann wird irgendwann mal vor dem Release anhand des letzten IO Reports,
der ja die händisch und automatisch gesetzten Eigenschaften (IOFF,
Driver, etc und eben auch die Terminierung) enthält, alles einzeln
abgehakt. Und man findet immer noch was, was man noch vergessen hatte
:-)
Jürgen S. schrieb:> Fpga K. schrieb:>> Wäre mir bewußt gewesen, das es überhaupt eine Input-Terminierung gibt,> Genau das war der Hintergrund meiner Frage.>> Wie gesagt, plädiere ich immer dafür, die Physik nicht im VHDL sondern> extern / drumherum zu gestalten. Bei den UCFs kann man sich überlegen,> ob man das trennt, also Synthese- und Impl. contraints.
Bei Speicherinterfacen wie in diesem Fall hat sich bei mir eingeprägt
möglichst wenig constraints "per Hand zu setzen", sondern dem MiG
(Memory Interface Generator) zu überlassen. Das verführt natürlich
fertige constraint-Blöcke unbesehen zu übernehmen (und damit eine
Terminierung zu aktivieren die man grad nicht braucht). Auch bei anderen
Interfacen wie JESD-204 (Hi-Speed AD/DA-Wandler) ist man immer mehr von
der eigentlichen "Physik" entfernt und überlässt Tools die
Interface-Generierung - ein bedauerlicher Trend?
MfG,