mikrocontroller.net

Forum: FPGA, VHDL & Co. Internes Signal "asynchron" fest auf '1' gelegt wird nicht erkannt.


Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe nach sehr langem Testen ein für mein Empfinden äußerst 
komisches Verhalten bei meinem VHDL Code festgestellt. Ich versuche es 
mal kurz zusammenzufassen:
Ich habe eine Schnittstelle umgesetzt, welche Signale nach außen 
sendet/schreibt und empfangen/lesen kann. Die Schnittstelle wird in 
meinem Top-Level instanziiert, mit einem enable-Signal wird der Lese- 
oder Schreibprozess gestartet und mit einem internen Signal readWrite 
wird festgelegt, ob geschrieben oder gelesen werden soll. Alles 
funktioniert wunderbar.
In einer Test-Anwendung muss nun nur geschrieben werden. Um keinen 
Aufwand zu haben, hatte ich in der port map das readWrite Signal einfach 
fest auf '1' gesetzt. Die Verhaltens-Simulation zeigte weiterhin das 
gewünschte Verhalten. Bei einer Post-Translate-Simulation war das 
Verhalten jedoch ziemlich verwirrend und entspricht nicht dem 
erwarteten. Nach langem hin und her hatte ich festgestellt, dass es an 
der festen Zuweisung von readWrite gleich '1' liegt. Verwende ich für 
readWrite ein Signal, welches einfach in einem getakteten Prozess fest 
auf '1' gesetzt wird, funktioniert wieder alles. Die Abfrage innerhalb 
der Schnittstelle ist allerdings ebenfalls getaktet und fragt bei enable 
lediglich ab, ob readWrite gleich '0' oder '1' ist.
Das komische ist nun weiterhin, dass das Verhalten bei fester Zuweisung 
auf '1' weder dem Verhalten für '1' noch dem Verhalten für '0' 
entspricht, sondern eben sehr seltsam ist...
Die "komischen" Ergebnisse der Timing-Simulation wurden durch Messung 
mit dem Oszi bestätigt. Es ist also kein Simulationsfehler, sondern 
entspricht der Realität.

Ich weiß wie gesagt was der Fehler ist und wie er behoben werden kann:
Sobald readWrite entweder asynchron oder in der port map fest auf '1' 
gesetzt wird, ist das Verhalten nicht wie erwartet. Wird ein getakteter 
Prozess verwendet, in welchem readWrite fest auf '1' gesetzt wird, geht 
alles.
Jetzt würde gerne verstehen warum das so ist bzw. woran das liegen kann.

Vielen Dank im Voraus für eure Hilfe und Erklärungen!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> Sobald readWrite entweder asynchron oder in der port map fest auf '1'
> gesetzt wird, ist das Verhalten nicht wie erwartet.
Was passiert, wen dieses signal ein Portpin ist, der auf einen 
definieren Pegel gelegt wird?

> Verwende ich für readWrite ein Signal, welches einfach in einem
> getakteten Prozess fest auf '1' gesetzt wird, funktioniert wieder alles.
Dieses Verhalten deutet auf ein Timingproblem durch wegoptimierte und 
gekürzte Pfade hin. Ausgangspunkt dieses Verhaltens sind gern 
irgendwelche asynchronen Pfade oder Resets im System.

Man müsste für eine brauchbare Analyse also mal die fragliche 
Beschreibung sehen...

> Jetzt würde gerne verstehen warum das so ist bzw. woran das liegen kann.
Es könnte auch ein Fehler oder eine Eigenheit der bisher unbekannten 
Toolchain beim bisher unbekannten FPGA sein.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die schnelle Antwort.

Es handelt sich um einen Xilinx Spartan-6 LX9 (auf dem Avnet MicroBoard 
Entwicklungsboard).
Verwendet habe ich ISE Version 14.7. Simuliert wurde mit ISim.

Leider bin ich mir nicht ganz sicher, was genau mit "Portpin" gemeint 
ist. Eine "abgespeckte" Version meines Codes (zeigt gleiches Verhalten) 
ist hier:
use IEEE.STD_LOGIC_1164.ALL;

entity tmp is
   Generic (CLKIN_PERIOD : real := 10.0);
    Port ( enable : in std_logic;
        clk : in std_logic; 
        rst : in std_logic; 
        out1 : out std_logic;
          out2 : out std_logic;
        out3 : out std_logic;
        out4 : out std_logic
       );
end tmp;

architecture Behavioral of tmp is


  signal selectController : integer range 1 to 3;
  signal writeAllRegToDriver : std_logic; 
  signal writeOneRegToDriver : std_logic; 
  signal regAddress : std_logic_vector(2 downto 0); 
  signal dataToIntReg : std_logic_vector(11 downto 0); 


  component SPI_writeReg   
    Port (  clk : in  STD_LOGIC;    
        enable : in STD_LOGIC;   
        rst : in STD_LOGIC;  
        selectController : in integer range 1 to 3;
        writeAllRegToDriver : in std_logic; 
        writeOneRegToDriver : in std_logic; 
        regAddress : in  std_logic_vector(2 downto 0);
        dataToIntReg : in std_logic_vector(11 downto 0);
        SCS : out  STD_LOGIC; 
        SCLK : out  STD_LOGIC;
        DATAtoDRIVER : out  STD_LOGIC;
        writeDone : out std_logic
      ); 
  end component; 
  
begin

  SPI_writeReg_inst : SPI_writeReg 
    port map ( clk => clk,    
          enable => enable,   
          rst => rst,  
          selectController => selectController,
          writeAllRegToDriver => writeAllRegToDriver,
          writeOneRegToDriver => writeOneRegToDriver,
          regAddress => regAddress,
          dataToIntReg => dataToIntReg,
          SCS => out1,
          SCLK => out2,
          DATAtoDRIVER => out3,
          writeDone => out4
          ); 
          

--process     
--begin
--wait until rising_edge(clk);
  dataToIntReg <= "000000000000";
  regAddress <= "000";
  writeAllRegToDriver <= '1';
  writeOneRegToDriver <= '0';
  selectController <= 1;
--end process; 
  
end Behavioral;

Wird process... einkommentiert, funktioniert alles. Ist der Teil 
auskommentierten, funktioniert es nicht.

Innerhalb von SPI_writeReg wird wie folgt abgefragt:
  process
  begin
    wait until rising_edge(clk);
    
   ...
    if enable = '1' then 
   ...
      if writeAllRegToDriver = '1' then
   ...

Der Tipp mit den wegoptimierten Pfaden hört sich sehr plausibel an. Kann 
ich das zum testen irgendwie ausstellen?

Nochmals vielen Dank für die Hilfe und die Bemühungen!!

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kann auch gerne den ganzen Code zur Verfügung stellen. Aber ich 
fürchte da werden einige die Hände über dem Kopf zusammenschlagen was da 
so wie gemacht wurde...

Autor: Schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Eingang "enable" ist nicht synchronisiert, wenn ich das richtig 
gesehen habe.
Eventuell liegt das Problem daran.

Das Timing ändert sich, abhängig davon, ob du die anderen Signale 
synchronisierst oder nicht.
Und dann tritt das letztendlich vom asynchronen enable verursachte 
Problem auf, oder auch nicht.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Schlumpf,
vielen Dank für die Antwort. Ich habe das etwas unschön hingeschrieben. 
Das enable ist in dem gleichen Prozess und nach dem wait until. Es 
sollte also alles synchronisiert sein.

Autor: Mike (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> Hallo Schlumpf,
> vielen Dank für die Antwort. Ich habe das etwas unschön hingeschrieben.
> Das enable ist in dem gleichen Prozess und nach dem wait until. Es
> sollte also alles synchronisiert sein.

Ich vermute mal, er wollte dich auf das Problem mit der Metastabilität 
hinweisen. Enable wird jetzt nicht aus einer anderen Taktdomäne 
gesteuert? Es wäre mir aber neu wenn die Tools deswegen Dinge 
wegoptimieren.

Was noch ein Problem sein könnte: gibt es eventuell noch eine andere 
Stelle wo du das Signal beschreibst? Oder wird es nie gesetzt? Du 
solltest dir mal alle Warnungen anschauen die ISE so ausspuckt.

Autor: Vancouver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist wahrscheinlich nicht der Grund, aber "wait until" in einem 
synthetiserten process ist zumindest etwas ungewöhnlich. Es ist 
syntaxmäßig nicht verboten, aber viele Synthesetools wollen hier lieber 
ein "if rising_edge(clk) then .. else" sehen. Das steht zumindest in den 
Guidelines von Xilinx überall so drin, und nach meiner Erfahrung sind 
manche Tools etwas zickig, wenn man es anders macht

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mike schrieb:
> Du solltest dir mal alle Warnungen anschauen die ISE so ausspuckt.
Dabei im Besonderen auf "Latches" oder "Combinatorial Loops" achten.

Wieviele Takte hast du in dem Design (alles mit 'event oder 
rising_edge() oder falling_edge() ist ein Takt)?

Vancouver schrieb:
> Ist wahrscheinlich nicht der Grund, aber "wait until" in einem
> synthetiserten process ist zumindest etwas ungewöhnlich.
Jeder Synthesizer kann seit gut 10 Jahren das "wait until" sinnvoll 
interpretieren.

> Es ist syntaxmäßig nicht verboten, aber viele Synthesetools wollen hier
> lieber ein "if rising_edge(clk) then .. else" sehen.
Ich weiß, es ist Pfennigfuchserei, aber kein Synthesetools möchte nach 
einem "if rising_edge() then" noch ein "else" sehen... ;-)

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Ich weiß, es ist Pfennigfuchserei, aber kein Synthesetools möchte nach
> einem "if rising_edge() then" noch ein "else" sehen... ;-)

hmm, Stichwort 'asynchroner Set/Reset'?
Ich weiss, klassisch schreibt man das andersrum, aber so geht's auch...

Autor: Schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> Das enable ist in dem gleichen Prozess und nach dem wait until. Es
> sollte also alles synchronisiert sein.

Das verstehe ich nicht ganz.. du verbindest in deinem Design den 
enable-Port direkt mit dem enable-Eingang des SPI. Damit ist es nicht 
synchronisiert.

Wenn du einfach nur eine Zeile wie z.B.
enable_sync <= enable;
vergessen hast, dann fehlt da aber auch noch die Signaldeklaration des 
synchroniserten Signals und auf das SPI ist dann auch das falsche Signal 
gemapped.

Bist du sicher, dass wir vom Gleichen reden?

Autor: Dominik (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nochmals vielen Dank für die Kommentare und Tipps.

Zu den einzelnen Punkten: Es wird nur ein Taktsignal verwendet. Enable 
wird auch nur an einer Stelle gesetzt. Um sicher zu gehen, habe ich auch 
alle wait until durch if rising_edge (und die Sensitivity list) ersetzt, 
leider ohne Erfolg.
Sämtliche ausgegebenen Warnungen beziehen sich auf "Signal hat 
konstanten Wert / Signal ist gleich einem anderen Signal. Das FF/Latch 
wird im Optimierungsprozess entfernt." oder "Signal ist nicht 
verbunden". Da ich nur einen Teil der beschriebenen Hardware verwende, 
sind diese Warnungen natürlich logisch und nachvollziehbar.

Wenn ich mir das RTL Schematic anschaue, dann wird bei getaktetem 
writeAllRegToDriver <= '1'; das Signal direkt mit VCC verbunden. Ist 
writeAllRegToDriver <= '1'; asynchron, dann ist die Leitung einfach 
nicht verbunden.
Daher würde ich gerne nochmal versuchen das "Optimieren" zu 
unterdrücken. Gibt es da eine Einstellung um ISE zu sagen, dass nichts 
entfernt werden soll?

Falls jemand Zeit und Lust hat sich das einmal anzuschauen, ich habe den 
Code jetzt doch angehängt. Die Top-Level Datei ist tmp.vhd

Autor: Schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... und was machst du mit deinem enable im toplevel?
synchronisierst du das? Sieht zumindest so aus, als wäre das nicht der 
Fall

Autor: Dominik (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Schlumpf,

du hast recht, das enable-Signal wird hier nicht einsynchronisiert. Das 
hatte ich bei der "abgespeckten" Version vergessen. Allerdings ändert 
das leider auch nichts. Bei der "realen" Anwendung hatte ich noch eine 
entsprechende Stufe davor geschaltet.
Wobei ich dachte, dass bei einer taktsynchronen Abfrage des 
enable-Signals und Einhaltung aller Timing-Constraints zumindest in der 
Simulation mit einem sauberen Übergang der Signale ohne Spikes, 
Rauschen, Jitter usw. das an dieser Stelle egal sein sollte (auch wenn 
es dann in der Realität vielleicht nicht zuverlässig laufen würde...).

Bei dem obigen Code hatte ich die Test-Bench vergessen. Diese habe ich 
hier noch angehängt.

Autor: Schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> Wobei ich dachte, dass bei einer taktsynchronen Abfrage des
> enable-Signals und Einhaltung aller Timing-Constraints zumindest in der
> Simulation mit einem sauberen Übergang der Signale ohne Spikes,
> Rauschen, Jitter usw. das an dieser Stelle egal sein sollte (auch wenn
> es dann in der Realität vielleicht nicht zuverlässig laufen würde...).

Das enable-Signal wirkt in deinem Desing auf viele Register.
Diese Register sind synchron zueinander (alle haben den gleichen Takt)
Aber der logische Pfad vom enable-Pin bis zum Dateneinang der Register 
hat "irgendeine" Länge.
Kommt nun das enable-Signal zu einem beliebigen Zeitpunkt, so kann es 
passieren, dass die Information bei einem Teil der Register noch 
rechtzeitig vor der Taktflanke da ist und somit übernommen wird.
Bei einem anderen Teil der Register kann es passieren, dass sie 
Metastabil werden, wenn tsu unterschritten wird. Und bei einem weiteren 
Teil der Register kann es passieren, dass die Information erst nach der 
Taktflanke kommt und somit erst mit der darauffolgenden Flanke 
übernommen wird.
Wie du siehst, kann alles mögliche in deinem Design passieren, wenn du 
enable nicht synchronisierst.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
berndl schrieb:
> hmm, Stichwort 'asynchroner Set/Reset'?
> Ich weiss, klassisch schreibt man das andersrum
Das ist aber eigentlich prinzipiell falsch und könnte sogar bei einer 
Verhaltenssimulation zu Race-Conditions führen (Stichwort Timestep).
Denn diese Beschreibung müsste dann "während" des steigenden Taktes 
(also für die theoretische Dauer 0) ein high am Ausgang zeigen:
  if rising_edge(clk) then
     ausgang <= '1';
  else 
     ausgang <= '0';
  end if;
Und diese Schaltung hier muss das bei aktivem Reset(!) tun:
  if rising_edge(clk) then
     ausgang <= '1';
  elsif reset='1' then
     ausgang <= '0';
  end if;

> aber so geht's auch...
Das hast du aber selber rausgefunden...  ;-)

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem einsynchronisieren sehe ich ein und ist natürlich völlig 
richtig. Ich habe es gleich nochmal probiert. Leider hat es mein 
aktuelles Problem auch nicht gelöst...

Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> Leider hat es mein
> aktuelles Problem auch nicht gelöst...

writeAllRegToDriver ist bei dir ja nur ein internes signal. Wenn du es 
fest auf 1 legst, dann hat der Synthesizer keinen Grund, ein solches 
Signal zu erzeugen. Sondern er kann die Abfragen des Signals schon zur 
Synthesezeit auswerten.  Also z.B. in deiner Abfrage

      if writeAllRegToDriver = '1' then
         Anweisungsblock1
      elsif ...
         Anweisungsblock2

wird er gleich nur den ersten Block synthetisieren. Der elsif-Teil wird 
ignoriert. Und damit braucht man auch kein Signal writeAllRegToDriver 
mehr, da keine if-Abfrage mehr übrig ist, die das Signal auswerten 
würde.

Wenn alles richtig läuft, brauchst du in der Simu also kein Signal 
writeAllRegToDriver zu sehen (das zu nichts mehr genutzt wird). Du 
solltest aber sehen, dass der erste Block deiner If-Abfrage 
synthetisiert wurde (und der zweite Block nicht).

Wenn du ein definiertes Signal writeAllRegToDriver sehen willst, dann 
kannst du das z.B. auf der Top-Ebene eine Kopie davon als Ausgang 
treiben - dann solltest du dort die erwartete 1 sehen können.

Autor: VHDL hotline (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es mit Initialwerten aus einem getakteten Prozess funktioniert und 
mit direkt angelegten nicht, passiert möglicherweise in dem allerersten 
Takt irgendwas Unerwartetes. Die getakteten Signale (zumindest die 
ungleich 0) sind ja erst im zweiten Takt an deiner weiteren Logik, die 
ungetakteten sofort. Im allerersten Systemtakt läuft das System da 
vielleicht schon in einen anderen Zustand.

Außerdem solltest du in deiner TB deine Signale nicht genau zur 
Taktflanke ändern, das hat schon gelegentlich zu Verwirrung mit 
Simulatordeltazyklen geführt.

Autor: Schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du auch den rst_port synchronisiert? Oder ist der im "echten" 
Design asynchron?

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank nochmal für die sehr interessanten und hilfreichen Tipps.

Es stimmt auf jeden Fall, dass sehr viel wegoptimiert wird. Und es ist 
natürlich ein guter Punkt, dass die if-Abfrage nach writeAllRegToDriver 
nicht umgesetzt wird, wenn diese immer gleich '1' ist. Wobei dieser Teil 
ja auch noch korrekt ausgeführt wird (zumindest scheinbar). Trotzdem 
natürlich ein logischer Punkt, den ich nicht richtig auf dem Schirm 
hatte.

Auch den Tipp mit der TB und dem Zeitpunkt der Änderung der Signale 
werde ich in Zukunft auf jeden Fall berücksichtigen. Danke!

Den Reset hatte ich auch synchronisiert. Da hatte ich mich auf der Seite 
von Lothar Miller schlau gemacht und viel dazu gelernt.

An den Reset als Übeltäter hatte ich auch schon gedacht. Jetzt hatte ich 
mich gewundert, warum die Adresse der Register regAddress_int zum Teil 
wegoptimiert wird, obwohl die sich eigentlich aendert. Dieses Signal 
hatte ich bei einem Reset nicht berücksichtigt, da ich dachte es wird 
sowieso sobald es verwendet wird neu gesetzt. Deshalb habe ich 
regAddress_int einfach ebenfalls bei einem Reset nochmals auf "000" 
gesetzt - und siehe da, es funktioniert. Ich muss leider zugeben, dass 
ich es immer noch nicht ganz verstehe warum. Ich dachte der 
Initialisierungswert eines std_logic_vectors sei überall 0 und das 
Signal wird ja bei einem enable überschrieben. Aber es liegt 
offensichtlich an der "Optimierung" und dem Reset...

Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> Jetzt hatte ich
> mich gewundert, warum die Adresse der Register regAddress_int zum Teil
> wegoptimiert wird, obwohl die sich eigentlich aendert.

sie ändert sich imho nicht. Im Block

   if writeAllRegToDriver = '1' then

weist du der regAddress_int eine Null zu.

Und die Case-Struktur, in der du die Adresse hochzählst, erreichst du 
nicht, weil die Bedingung

   SPI_waitBetweenWriteCycles(SPI_waitBetweenWriteCycles'left to 
....)="10"

nie erfüllt ist (du weist SPI_waitBetweenWriteCycles nie etwas anderes 
als 0 zu).

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt das "Optimieren" von regAddress_int mit dem Attribut KEEP 
unterdrückt und jetzt funktioniert alles!
Es liegt also tatsächlich daran, dass durch die Optimierung ein 
eigentlich benötigter Teil aus der Schaltung entfernt wird und dies dann 
zu einem Fehler führt.

Ich möchte mich hiermit noch einmal ganz herzlich für die vielen Tipps 
und hilfreichen Kommentare bedanken!!!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dominik schrieb:
> dachte der Initialisierungswert eines std_logic_vectors sei überall 0
Wenn kein Initialwert angegeben wird, kann sogar ein Register wie das 
hier wegoptimiert werden:
signal flag : std_logic;
:
process (clk) begin
  if rising_edge(clk) then   -- Ganz logisch: ein Takt
    flag <= '1';             -- ergibt ein Flipflop
  end if;
end process;
Denn der Synthesizer sieht, dass der Wert von flag eigentlich egal ist 
und dann auf '1' gesetzt wird. Also setzt er ihn sofort auf '1' gesetzt 
und kann entsprechende Codeteile wegoptimieren. Und jetzt kommt der 
überraschende Trick: das passiert sogar, wenn ein enable im Spiel ist:
signal flag : std_logic;
:
process (clk) begin
  if rising_edge(clk) then   -- Ganz logisch: ein Takt
    if enable='1' then       -- mit enable
      flag <= '1';           -- ergibt ein Flipflop
    end if;
  end if;
end process;

Erst mit Initialisierung wird tatsächlich ein Flipflop daraus...

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Again what learned ;-) Man muss wirklich an allen Ecken und Enden 
aufpassen...

Vielen Dank für die Erklärung!!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.