Forum: FPGA, VHDL & Co. phase Correct PWM


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Armin D. (okepasst)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich bin leider noch eine Anfänger in VHDL. Die Aufgabe die Ich hier zu 
machne habe ist im Anhang. Ich hab ein paar Fragen und hoffe das Ihr mir 
da vll helfen könntet. Im Anhang findet ihr außerdem meinen momentanen 
Stand der Dinge.

Nun zu meinen Fragen:
Ich hab mich schon informiert wie ein PWM Signal aussieht und was es 
machen soll. Leider weiss ich aus dieser Erkenntnis immernoch nicht ganz 
wie ich es schaffen soll so ein Signal zu erzeugen welches über 5 
Bits(schalter) die "Flanken" regeln sollen.

Außerdem bin ich mir nicht ganz sicher was mit Phase correct gemeint 
ist. und um ehrlich zu sein bringt mir die kleine Hilfe Stellung weiter 
unten auch nichts.

Würd mich freuenen wenn ich so schnell wie möglich Klarheit erfahren 
dürfte.
mfg

von Gustl B. (-gb-)


Lesenswert?

Ob die Zähler hoch und runter zählen oder nur hoch ist egal.

Armin D. schrieb:
> Phase correct

meint hier, dass die beiden PWMs schön übereinander liegen und nicht 
gegeneinander verschoben sind. Also die Mitten der beiden High und Low 
Pegel beider PWMs müsssen deckungsgleich sein, zeitlich.

Ja ... mit so einer PWM die hoch und runter zählt oder so, kannst du 
einen 6 Bit Zähler nehmen. Der hat dann 64 Takte. Und in Anhängigkeit 
des Zählerstandes gibst du die PWM symmetrisch um dessen Mitte herum 
aus.

PWM_ausgang <= '0' when (Zähler < 31 - unsigend(BREITE(4 downto 0)) and 
zähler < 32)
or
(zähler - 32 > unsigned(BREITE(4 downto 0)) and zähler > 31)
else '1';

Jedenfalls irgendwie so, ist vermutlich nicht korrekt, habe ich nicht 
simuliert.

Ich verstehe bei dir die Ports schon nicht. Du brauchst doch nur je PWM 
einen 5 Bit breiten Eingang und einen 1 Bit Ausgang.

Die Generics brauchst du hier gar nicht, das sind Dinge die du in der 
ebenfalls zu schreibenden Testbench einstellst.

Edit:
Du kannst natürlich auch einen Zähler hoch und runter zählen lassen. 
Kommt auf das Selbe raus.

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

OK, oben der Code ist fehlerhaft. Nur mit Vergleichen > und < brauche 
ich eine zusätzliche Ausnahme für einen der Werte 31 oder 0.

von Duke Scarring (Gast)


Lesenswert?

Armin D. schrieb:
> Leider weiss ich aus dieser Erkenntnis immernoch nicht ganz
> wie ich es schaffen soll so ein Signal zu erzeugen welches über 5
> Bits(schalter) die "Flanken" regeln sollen.

Ich finde hier hat der Aufgabenersteller verwirrende Begrifflichkeiten 
verwendet. Mit Flanke kann sowohl der Zeitpunkt (hier naheliegend) als 
auch die Flankensteilheit gemeint sein. Außerdem gibt es nach meinem 
bisherigen Kenntnisstand keine allgemein verbreitete Definition für 
'phase correct PWM'.
Ich würde da einfach nochmal nachhaken.

Für mich besteht ein PWM-Signal aus einer Periodendauer (bzw. Frequenz) 
und einem Tastgrad (im Bereich zwischen 0 und 100%).

Man könnte jetzt mutmaßen, das zwei PWM-Signale erzeugt werden sollen, 
deren Tastgrad jeweils über die DIP-Schalter eingestellt werden können 
soll. Zusätzlich sollen die Signale noch eine irgendwie definierte 
Phasenbeziehung haben.

Duke

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Hallo, ich habe die PN bekommen und möchte hier antworten:

Ich verstehe das mit den PWMs so:
Ziel sind zwei PWMs die unterschiedlichen Tastgrad haben können. Der 
wird also jeweils über 5 Schalter eingestellt.

Die Besonderheit hier ist, dass die PWM quasi immer doppelt ist. Wie 
gespiegelt und zwar soll der Bereich der High Phase um das Zählermaximum 
herum symmetrisch sein - so zumindest die Zeichnung.

Jetzt gibt es zwei Möglichkeiten, du kannst von 0 bis 31 zählen und dann 
wieder zurück nach 0. Dabei solltest du aber die 0 und die 31 zweimal 
erreichen da jeder andere Zählerstand ebenfalls doppelt vorkommt.
Die andere Möglichkeit ist von 0 bis 63 zu zählen und dann wieder bei 0 
zu beginnen. Dann muss die Highpase um die 31/32 herum symmetrisch sein.

Beispiel:
Angenommen du stellst mit den Schaltern den Wert 5 ein und zählst hoch 
und wieder runter.
Dann gibst du so lange eine 0 aus wie dein Zähler kleiner oder gleich 
31-5 ist. Also bei den 5 Zählerständen 31, 30, 29, 28 und 27 gibst du 
eine 1 aus. Und das machst du ebenfalls wenn du wieder runtter zählst.

Bei der anderen Möglichkeit mit nur hochzählen bis 63 gibst du die 1 aus 
wenn der Zählerstand 27, 28, 29, 30, 31, da ist die Mitte, 32, 33, 34, 
35 und 36 ist. Dann ist das schön symmetrisch um die Mitte des 
Zählerbereiches herum.

Wenn du das bei beiden PWMs gleich machst werden die automatisch 
zueinander phasengleich.

Aber der erste Schritt ist eigentlich eine Testbench zu schreiben die 
die 2x 5 Schalter bespaßt und einen Takt mit 50 MHz anlegt.

Im Anhang findest du eine Testbench die ales macht was in der Aufgabe 
verlangt ist. Da musst du nichts ändern.
Zusätzlich ist auch ein Gerüst der PWM Komponente dabei. Das hat schon 
die passenen Schnittstellen. Deine Aufgabe ist das mit Leben zu füllen. 
Also die Schalterstellungen auszuwerten und an den beiden 1-Bit PWM 
Ausgängen eine 1 oder 0 auszugeben.

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


Lesenswert?

Duke Scarring schrieb:
> Man könnte jetzt mutmaßen, das zwei PWM-Signale erzeugt werden sollen
Ich sehe das auch so: es ist 2x die selbe kombinatorische 
Vergleichereinheit-Einheit, die von einem Zähler angestuert wird, der 
laufend zwischen 0 und 31 und wieder zurück zählt.

Man braucht also 1x den Auf-Ab-Zähler und 1x den Vergleicher, der dann 
2x als Komponente instantiiert wird.

Gustl B. schrieb:
> Jetzt gibt es zwei Möglichkeiten, du kannst von 0 bis 31 zählen und dann
> wieder zurück nach 0. Dabei solltest du aber die 0 und die 31 zweimal
> erreichen da jeder andere Zählerstand ebenfalls doppelt vorkommt.
Das sehe ich bei der Aufgabenstellung hier nicht so. Ich würde da so 
zählen:

...29,30,31,30,29...2,1,0,1,2...29,30,31,30,29...2,1,0,1,2...

Wobei man dann blöderweise natürlich statt der erwarteten 64 
Zählschritte tatsächlich nur 62 Schritte für einen kompletten PWM-Zyklus 
braucht  :-/

Halb so schlimm, denn da kommt (wie bei jeder PWM) sowieso noch das 
"Problem" mit Dauer-'0' und Dauer-'1'. Definiert ist in der Aufgabe 
hier, dass der Einstellwert von 0 bis 31 geht, deshalb darf der Zähler 
also entweder nur von ..0..30..0..30.. zählen. Dann würde ein Vergleich 
wie der hier das gewünschte Bild bringen:
1
if pwmval>cnt then    pwmout<='1';
2
else                  pwmout<='0';
3
end if;

Oder der Zähler darf nur von 1..31 zählen und die Abfrage sieht dann so 
aus:
1
if pwmval<cnt then    pwmout<='0';
2
else                  pwmout<='1';
3
end if;

Und weil der Zähler jetzt zudem noch einen Schritt "früher umdreht" und 
deshalb noch weniger zählt, braucht er letztlich sogar nur 60 
Zählschritte bzw. Taktimpulse für einen kompletten Durchlauf  :-o


Weil 5 Bit schon unhandlich groß sind hier mal exemplarisch der nötige 
Zähler für einen 3 Bit Vorgabewert:
1
cnt         0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1,   0, 1, 2, 3, 4, ...
2
             \/
3
taktflanke    1  2  3  4  5  6  7  8  9 10 11 12    1  2  3  4  5...
Nach 12 Takten sind wir wieder bei cnt=0

Und zusammen mit obigem Vergleich:
1
if pwmval>cnt then    pwmout<='1';
2
else                  pwmout<='0';
3
end if;
... und pwmval=0..7 ergibt sich das gewünschte Verhalten:
- bei pwmval=0 ist pwmout immer '0'
- bei pwmval=7 ist pwmval immer '1'

Bei 3 Bit könnte man ja naiv 2x 8 Zähltakte erwarten, tatsächlich 
bleiben nur 12 übrig. Und genau die hier fehlenden 4 Takte fehlen auch 
bei der 5 Bit PWM.

PS: Das verwirrende Bild der Signalverlaufs in der aufgabenstellung (das 
eigentlich falsch herum gezeichnet ist, denn laut diesem Bild würden 
höhere Werte für N0 und N1 eine kürzere High-Dauer bewirken!) und der 
umständliche "Hinweis" auf das deshalb anzuwendende Einerkomplement 
macht es übrigens nicht leichter, die Sache zu verstehen.
Da hat sich schon der Aufgabensteller selbst ein Bein gestellt, ist 
glatt drüber gestolpert und hat die schöne Aufgabenstellung etwas 
vermurkst.

PS2: Man sollte hier übrigens die Übernahme von neuen Vergleichswerten 
nur beim niedrigsten Zählerstand zulassen, weil sonst böse Spikes im 
Ausgangssignal auftreten können.

: Bearbeitet durch Moderator
von Armin D. (okepasst)


Angehängte Dateien:

Lesenswert?

Hallo,danke für die Hilfe, sowas ist nicht selbstverständlich schätze es 
sehr.

Nun hab ich meinen Lehrer nochmal gefragt wie die Aufgabenstellung im 
genauen gemeint war, dabei kam raus das ich von 0 bis 31 zählen soll und 
dann wieder runter.
Außerdem hab ich den Code soweit umgeschrieben, dass ich den Zähler fürs 
auf und abzählen schonmal hab.

Zum Pwm Signal kam follgende Erklärung: die Halbe Periode sind 32 
Tacktschritte(inkl. 0), daher soll geprüft werden auf welchen Wert die 
Schalter gesetzt sind und ab dem erreichen des Wertes soll das signal 
auf 1 gesetzt werden bis die Taktschritte beim runterzählen kleiner als 
der eingestellte Wert ist. Dann soll wieder 0 rauskommen.

Leider bin ich nun auf mein nächstes problem gestoßen: und zwar hatte 
ich vor die Schritte mit dem eingestellten Wert zu vergleichen. Leider 
kommt mir hier eien Fehlermeldung, da es sich bei beiden um ein Vector 
handelt und es nicht so einfach verglichen werden kann.

Hab mir außerdem deinen lösungsvorschlag angeschaut hab mal meinen Code 
darauf geändert hoffe das ich es richtig verstanden hab.

Der Code ist wieder im Anhang.
Hoffe wieder auf so eine Tolle Hilfe.

von Achim S. (Gast)


Lesenswert?

Armin D. schrieb:
> Leider
> kommt mir hier eien Fehlermeldung, da es sich bei beiden um ein Vector
> handelt und es nicht so einfach verglichen werden kann.

dann solltest du möglichst den genauen Wortlaut der Fehlermeldung mit 
beschreiben.

Du arbeitest mit unsigned-Werten (was in Ordnung ist). Aber bei der 
Breite der Werte wechselst du fröhlich durch.

Hier z.B.
if(pwm0 < to_unsigned(31,n_Bit))  then
vergleichst du einen 5 Bit breiten unsigned mit einem 10 Bit breiten 
unsigned. Die können tatsächlich nie identisch sein. Aber warum wählst 
du auf der rechten Seite des Vergleichs eine Breite von 10 Bit?

Und warum lässt du hier
    Upwm1             : in std_logic_vector(n_Bit-1 downto 4);     -- 5 
Bit for parallel load
den Bereich von 9 downto 4 laufen statt von 5 downto 0? (und das kann 
sich bei der Instantiierung sogar noch ändern, wenn das generic n_Bit 
überschrieben wird).

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


Lesenswert?

Armin D. schrieb:
> Der Code ist wieder im Anhang.
1
 signal  pwm0     :unsigned(n_Bit-6 downto 0):= (others=>'0');
2
 signal  pwm1     :unsigned(n_Bit-1 downto 4):= (others=>'0');
Was ist das denn? Das sind doch deine Zähler, auf jeden Fall zählst du 
doch darauf rum. Warum haben die solche kruden Bereiche? Warum müssen 
beide Zähler unbedingt in 1 Vektor stecken? Das macht niemand so.

Ich würde zum Zählen und Vergleichen hier sowieso Integer nehmen, dann 
müsste ich nur den die beiden Schalterwerte in zwei 
Integer-Vergelcihswerte umwandeln und könnte alles ohne Casts und 
Konvertierungen hinschreiben.

Und warum registrierst du das Signal pwm nochmal?
Probiers mal so:
1
--  pwm_logic:process(clk_in)
2
--  begin
3
--    if(rising_edge(clk_in)) then
4
      if(pwm0 => Upwm0) then
5
        pwm <= '1';
6
      else 
7
        pwm <= '0';
8
      end if;
9
--    end if;
10
--   end process pwm_logic;


Und warum zum Schluss das vergebliche Umwandeln von std_logic nach 
std_logic?
Upwm0_out <=  std_logic(pwm);


Der ganz "Code" sieht mir genauso aus, als ob ein Softwareprogrammierer 
gestern noch Software in C und heute Hardware in VHDL "programmiert".

Wenn ich versuche, diesen Code in meinem Kopf in Hardware umzuformen, 
dann bekomme ich das nicht hin. Und offenbar geht es dem Synthesizer 
nicht besser...

Lies mal den Beitrag "Re: Code beeinflusst Geschwindigkeit, Richtlinien" und 
versuche zu verstehen, was ich dort in der zweiten Hälfte des Beitrags 
geschrieben habe: du zeichnest ein Bild von einer Schaltung, die das 
macht, was du willst, auf ein Blatt Papier.
Dann nimmst du statt eines Schaltplaneditors den Texteditor und 
schreibst einen VHDL-Code, der diese Schaltung beschreibt. Und dann 
hoffst du, dass der Synthesizer deine Beschreibung versteht und in die 
Schaltung umsetzt, die du dir ursprünglich ausgedacht hast.

Armin D. schrieb:
> Nun hab ich meinen Lehrer nochmal gefragt wie die Aufgabenstellung im
> genauen gemeint war, dabei kam raus das ich von 0 bis 31 zählen soll und
> dann wieder runter.
Viel Spaß bei der Implementierung des Dauer-0 bzw -1 Geraffels.

: Bearbeitet durch Moderator
von Armin D. (okepasst)


Angehängte Dateien:

Lesenswert?

Kleine korrektur zu dem Code, da mir aufgefallen ist das es noch ein 
alter Stand war.

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


Lesenswert?

Armin D. schrieb:
> Kleine korrektur zu dem Code
Du solltest unbedingt die Antworten auf deine Posts lesen und verstehen.
Und an Besten gleich nachfragen, wenn eines davon nicht klappt...

von Armin D. (okepasst)


Lesenswert?

Lothar M. schrieb:

> Ich würde zum Zählen und Vergleichen hier sowieso Integer nehmen, dann
> müsste ich nur den die beiden Schalterwerte in zwei
> Integer-Vergelcihswerte umwandeln und könnte alles ohne Casts und
> Konvertierungen hinschreiben.

Leider verstehe ich nicht was du hiermit meinst, bzw ist die 
Aufgabenstellung das ich diese bits beliebig verändern kann daher fehlt 
es mir schwer das ich hiermit Integer arbeite.

>
> Der ganz "Code" sieht mir genauso aus, als ob ein Softwareprogrammierer
> gestern noch Software in C und heute Hardware in VHDL "programmiert".
>

Tja das ist auch genau der, Fall weshalb ich gehofft habe hier ein paar 
Antworten zu finden

von Gustl B. (-gb-)


Lesenswert?

Lothar M. schrieb:
> PS: Das verwirrende Bild der Signalverlaufs in der aufgabenstellung (das
> eigentlich falsch herum gezeichnet ist, denn laut diesem Bild würden
> höhere Werte für N0 und N1 eine kürzere High-Dauer bewirken!)

Ist das so? Es könnte auch sein, dass die Highpase eben dann 
stattzufinden hat wenn auch der Zähler oben ist.

Aber das mit dem Zähler ist in der Aufgabenstellung auch nicht 
definiert. Die Zeichnung ist nur ein Lösungsvorschlag.

Lothar M. schrieb:
> PS2: Man sollte hier übrigens die Übernahme von neuen Vergleichswerten
> nur beim niedrigsten Zählerstand zulassen, weil sonst böse Spikes im
> Ausgangssignal auftreten können.

Das macht Sinn und sollte man machen, steht aber auch nicht in der 
Aufgabe.

Reset und das mit dem Generic stehen da auch nicht drinnen.

Lothar M. schrieb:
> Viel Spaß bei der Implementierung des Dauer-0 bzw -1 Geraffels.

Dass steht leider schon in der Aufgabenstellung. Die Dauer der Highphase 
soll doppelt so lang sein in Takten wie der eingestellte Wert. Und 
insgesamt soll das dann 64 Takte Periodendauer haben.
Aber egal, das ist nicht viel zusätzliche Beschreibung, die Lösung der 
Aufgabe ist eher sehr knapp.

Armin D. schrieb:
> Tja das ist auch genau der, Fall weshalb ich gehofft habe hier ein paar
> Antworten zu finden

Dann fang doch zuerst mit kleinen Schritten an.
Bei meinen Schülern gab es auch Aufgaben die sich schrittchenweise 
gesteigert haben.

Man kann die Aufgabe schön zerlegen:

1. Schreibe einen Zähler der eine Periodendauer von 64 Takten hat. Ob du 
da jetzt hoch und runter oder nur hoch oder nur runter zählst ist nicht 
festgelegt in der Aufgabe, mach das wie du willst.

2. Gebe in Abhängigkeit vom Zählerstand erstmal sehr einfach ein Signal 
aus. Z. B. lege das Ausgangssignal immer auf '1' wenn der Zähler über 
der Hälfte ist und sonst auf '0'.

3. Gebe ein Signal aus und zwar jetzt in Abhängigkeit der 
Schalterstellung, also eines 5-Bit Wertes und des Zählerstandes.

-------------------

- 2 und 3 kann man komplett getrennt von 1 machen und auch nur 
kombinatorisch ohne process.
- Simuliere jeden Teilschritt und überzeuge dich davon, dass der 
funktioniert wie gewünscht. Ich hatte oben eine Testbench hochgeladen 
die für diese Aufgabe wunderbar passt.
- Lass das mit der Generic und dem Reset erstmal weg, das ist hier nicht 
gefragt in der Aufgabe und stiftet nur Verwirrung.
- Du braucht für die beiden PWMs nur einen einzigen Zähler. Das macht es 
einfacher am Ende keine Phasenverschiebung zu bekommen.

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


Lesenswert?

Also vergiss erst mal die PWM und beschreibe zuerst (wie dein Lehrer 
auch empfohlen hat) einen Zähler, der einen Integer mit range 0 to 31 
ständig auf und ab zählt.

Lass diesen Zähler in einer Testbench laufen.

Wenn dieser Zähler funktioniert, dann erst(!!) kommt der Schritt mit den 
beiden Vergleichern.

von Duke Scarring (Gast)


Angehängte Dateien:

Lesenswert?

Hier, Teil 1 zur Motivation...

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


Lesenswert?

Gustl B. schrieb:
> Es könnte auch sein, dass die Highpase eben dann stattzufinden hat wenn
> auch der Zähler oben ist.
Das schon, aber die Pulsdauer ist tatsächlich so krude definiert:

N=31 → Signal gänzlich auf High

N=0 → Signal gänzlich auf Low

Und es steht da:  ton = 64  -  2*N

Somit tritt der kürzeste, der "loweste" PWM Puls bei N=30 mit 4 Takten 
'1' auf. Und bei N=31 muss dann aber Dauer-High ausgegeben werden.

Bei N=1 ist der Ausgang mit Ton = 64-2 = 62 dann ziemlich "high". Und 
wird bei N=0 dann schlagartig dauernd Low.

Den PWM-Impuls mit 2 Takten '1' pro Zyklus gibt es hier gar nicht 
(deshalb sagte ich "Gehampel" )

von Gustl B. (gustl_b)


Lesenswert?

Das stimmt. Dann passt diese handschriftliche Lösungsvorschlag nicht 
ganz zur Aufgabe. Punktabzug für den Lehrer.

Meine Erwartung bei der Aufgabenstellung war dass die Periode immer 64 
Takte lang ist und die Highphase doppelt so viele Takte lang ist wie mit 
den Schaltern eingestellt wurde. Das lässt sich auch recht einfach 
bauen.

Ja, du hast recht, dieser Lösungsvorschlag ist Gehampel.

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


Lesenswert?

Duke Scarring schrieb:
> Hier, Teil 1 zur Motivation...
Ich würde da einen durchlaufenden 0..63 Zähler machen und bei gesetzem 
MSB dann cntout = 63-zaehler ausgeben:
1
signal cnt: unsigned (5 downto 0) := (others=>'0');
2
signal cntout : integer range 0 to 31; 
3
:
4
cnt <= cnt+1 when rising_edge(clk) ; - - 0,1..62,63,0,1..63,0..
5
cntout < to_integer(cnt)  when cnt(5)='0' else
6
              31-to_integer(cnt(4 downto 0)); -- 0,1,2..30,31,31,30..,2,1,0,0,1...
Und da ist bisher tatsächlich kein Prozess beteiligt... 😉

: Bearbeitet durch Moderator
von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Meine Erwartung bei der Aufgabenstellung war dass die Periode immer 64
> Takte lang ist und die Highphase doppelt so viele Takte lang ist wie mit
> den Schaltern eingestellt wurde.

Ich schau mal trotzdem das ich es wie du bereits erwähnt hast mal nur 
mit dem Counter probier, der bis 63 zählt und dann mit den einzelnen 
schritten weiter mache.

von Gustl B. (gustl_b)


Lesenswert?

Kannst du machen.

Wenn du einen Zähler bis 63 nimmt, dann ist der Zähler selbst einfacher 
aber die Ausgabe der PWM in dessen Abhängigkeit schwieriger.

Bei einem Zähler hoch und runter ist der Zähler schwieriger aber die PWM 
Ausgabe einfacher.

Am Ende nimmt sich das nix. Als Übung kannst du auch beide Varianten 
einbauen.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Wenn du einen Zähler bis 63 nimmt, dann ist der Zähler selbst einfacher
> aber die Ausgabe der PWM in dessen Abhängigkeit schwieriger.

Wie jetzt? Ich brauche ja einen Zähler der von 0 bis 31 hochzählt und 
dann wieder runter, das wären doch 63 Schirtte.
Also würde doch ein einfacher Zähler passen.

von Gustl B. (gustl_b)


Lesenswert?

Naja die PWM soll ja 64 Schritte lang sein.

Da kannst du einen 5 Bit Zähler nehmen und den bis 31 zählen und dann 
wieder runter zählen bis 0.

Du kannst aber auch einen 6 Bit Zähler nehmen und den bis 63 zählen und 
dann wieder auf Null setzen.

Das sind dann beides 64 Schritte. Das geht auch Beides und ist für die 
Aufgabe in etwa gleich schwierig oder gleich leicht.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Das sind dann beides 64 Schritte. Das geht auch Beides und ist für die
> Aufgabe in etwa gleich schwierig oder gleich leicht.

Also wäre es doch in etwa dieser code von oben.

signal cnt: unsigned (5 downto 0) := (others=>'0');
signal cntout : integer range 0 to 31;

cnt <= cnt+1 when rising_edge(clk) ;
cntout < to_integer(cnt)  when cnt(5)='0' else
              31-to_integer(cnt(4 downto 0));
Ps.: Der Code gibt folgende Fehler meldung aus

** Error: C:\intelFPGA_lite\18.1\PWM.vhd(23): near "<": (vcom-1576) 
expecting == or '+' or '-' or '&'.

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb:
> Also wäre es doch in etwa dieser code von oben.

Ja, wobei du den Code selber schreiben und verstehen solltest.

In dem Code oben gibt es cntout, das braucht man nicht zwingend, denn 
die Aufgabenstellung ist ja nicht einen Zählerstand auszugeben, sondern 
zwei nur davon abhängige PWMs.

Dann verwendet der Code oben when rising_edge(clk) ;
Ja, kann man machen, funktioniert auch, ist aber am Anfang vielleicht 
etwas verwirrend und es wäre für dich einfacher das alles in einem 
getakteten Prozess zu bauen.

Was sind denn diese Prozesse, Loops, Generate, Zahlen (Integer, 
Unsigned, ...), Variablen?
Die gibt es alle nicht in Hardware. Das ist reine Abstraktion und 
Interpretation. Das macht es dir einfacher die Hardware zu beschreiben 
ohne, dass du in Hardware denken musst oder es ersetzt Schreibarbeit.
Man braucht diese Dinge alle nicht zwingend.

Armin D. schrieb:
> ** Error: C:\intelFPGA_lite\18.1\PWM.vhd(23): near "<": (vcom-1576)
> expecting == or '+' or '-' or '&'.

Fehlermeldungen mit Zeilennummer machen nur Sinn wenn man auch den Code 
hat. Aber hier sollte statt < ein <= stehen.

: Bearbeitet durch User
Beitrag #6647827 wurde vom Autor gelöscht.
von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Ja, wobei du den Code selber schreiben und verstehen solltest.

Naja ich versteh ja wie das Programm funktioniert und ich brauch es ja 
eig auch genauso da es beim MSB umschaltet und dann beginnt 
runterzuzählen.

Soweit wäre ja dann der Zähler der Sowohl hoch als auch runter zählt 
fertig. Nun wäre doch der nächste Schritt die grenzen zu setzen wobei 
die PWM Signale bei unterschiedlicher Grenze auf 1 gesetzt werden und 
danach wieder auf 0

von Gustl B. (-gb-)


Lesenswert?

Ich meinte das anders.

Wenn du einen Zähler hast der hoch und runter zählt, dann gibst du die 1 
aus wenn der Zählerstand > Grenze ist. (Auch < Grenze wäre denkbar).

Wenn du einen Zähler hast der nur von 0 bis 63 zählt, dann hast du zwei 
Grenzen die symmetrisch um die 31/32 herum liegen.

Aber du kannst das so machen mit dem Code von Lothar.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Wenn du einen Zähler hast der hoch und runter zählt, dann gibst du die 1
> aus wenn der Zählerstand > Grenze ist. (Auch < Grenze wäre denkbar).
>
> Wenn du einen Zähler hast der nur von 0 bis 63 zählt, dann hast du zwei
> Grenzen die symmetrisch um die 31/32 herum liegen.

Aso also meinst du es wäre fürs spätere PWM, einfache die Symmetrie 
beizubehalten?


Hab auch ein wenig weitergemacht steck leider wieder fest
Nach dem oberen code habe ich noch das hier dazu geschrieben. Dabei hab 
ich es mir folgendermaßen ausgedacht. Solange das MSB nicht gesetzt ist 
soll PWM_out, (welches ich schon folgender maßen eingebaut habe:)

signal PWM_out:  std_logic :='0';

auf 0 sein und etwa ab der Hälfte dann auf 1 gesetzt werden.

PWM_out <= '0' when count(5)= '0' else
    PWM_out <= '1';    <- hier ist der Fehlercode

Nun zu meiner Fehlermeldung:

** Error: C:\intelFPGA_lite\18.1\PWM.vhd(27): Type error resolving infix 
expression "<=" as type ieee.std_logic_1164.STD_LOGIC.

Ich schätze mal das ich etwas beim definieren verkehrt gemacht habe.

von Gustl B. (gustl_b)


Lesenswert?

Und so wäre es korrekt.

PWM_out <= '0' when count(5)= '0' else '1';

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:
> Und so wäre es korrekt.

> PWM_out <= '0' when count(5)= '0' else '1';

Danke Vielmals.

Nun Sollte doch eig die TB von vorhin funktionieren. Korrekt?

von Gustl B. (-gb-)


Lesenswert?

Welche? Teste das doch einfach, das dauert nur wenige Sekunden. Oder 
lade hier Code hoch, Testbench und deine PWM Komponente.

von Armin D. (okepasst)


Angehängte Dateien:

Lesenswert?

Weiss jetzt nicht genau was du mit komponenten meinst

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Oh Entschuldigung, in meiner Testbench hatte ich das noch nicht 
umbenannt. Im Anhang ist jetzt die richtige Testbench die die Komponente 
PWM korrekt einbindet.

von Armin D. (okepasst)


Angehängte Dateien:

Lesenswert?

Habs nun Ausprobiert ich bekomm aber komischer weise das hier raus

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Das siehst du in der Simulation, weil der interessante Teil innerhalb 
der ersten 1-2 us passiert. Also ganz am Anfang. Ausserdem siehst du 
PWM_out erstmal gar nicht, weil du das nicht mit einem Ausgang verbunden 
hast.

----- Antwort auf deinen vorherigen Post -------------------

Ja, korrekt, PWM_out wechselt jetzt seinen Pegel.

Der ist jetzt '0' wenn der Zähler hochzählt und '1' wenn der Zähler 
runterzählt.

Jetzt lassen wir mal die Schalter noch weg und gehen einen kleinen 
weiteren Schritt:

Stell dir vor mit den Schaltern wurde jetzt der Wert 8 eingestellt.

Jetzt soll die PWM immer '1' sein wenn der Zähler kleiner als 8 ist und 
sonst '0'.
Erklärung:
Kleiner 8 sind 0 bis 7, also genau die geforderten 8.

Du könntest alternativ auch eine '1' ausgeben wenn der Zähler größer als 
31 - 8. Das sind 24 ... 31 also ebenfalls 8 Schritte.

Ich hänge dir noch eine PWM.vhd an in der es den Wert Breite als 
Konstante gibt. Die hat den Wert 8 und die kannst du verwenden. Später 
wird die erstezt durch die Schalter.

Ausserdem habe ich deine PWM_out mal durch PWM_0 ersetzt, das ist ein 
Ausgang und den siehst du direkt in der Simulation ohne tiefer stochern 
zu müssen.

von Armin D. (okepasst)


Angehängte Dateien:

Lesenswert?

Gustl B. schrieb:

> Ausserdem habe ich deine PWM_out mal durch PWM_0 ersetzt, das ist ein
> Ausgang und den siehst du direkt in der Simulation ohne tiefer stochern
> zu müssen.

Ich hab jetzt mal das Programm auf die Breite verändert weiss leider 
aber nicht was du mit PWM_out verändert hast es ist  immernoch PWM_out.

von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb:
> verändert weiss leider
> aber nicht was du mit PWM_out verändert hast es ist  immernoch PWM_out.

Dann ersetze in dieser Zeile

PWM_out <= '1' when count >= BREITE else '0';

das PWM_out durch PWM_0.

Die Zeile
 signal PWM_out  :  std_logic :='0';
kannst du dann löschen.

Ja, du verwendest jetzt count um die PWM auszugeben. Aber count zählt 
nur von 0 nach 63 hoch. Das kannst du verwenden, aber dann brauchst du 
später zwei Grenzen die symmetrisch um die Mitte 31/32 liegen.

Du kannst aber auch countout verwenden. Dazu musst du aber noch BREITE 
in ein Integer wandeln für den Vergleich weil countout ja ein Integer 
ist.
Das geht mit to_integer(unsigned) wobei unsigned für eine beliebige 
unsigned Zahl steht wie BREITE. Du kannst also to_integer(BREITE) beim 
Vergleich mit countout schreiben.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Du kannst aber auch countout verwenden. Dazu musst du aber noch BREITE
> in ein Integer wandeln für den Vergleich weil countout ja ein Integer
> ist.
> Das geht mit to_integer(unsigned) wobei unsigned für eine beliebige
> unsigned Zahl steht wie BREITE. Du kannst also to_integer(BREITE) beim
> Vergleich mit countout schreiben.

Weiss jetzt ehrlich gesagt nicht genau wo ich das hier machen sollte
1
begin
2
-- hier ungetaktete Kombinatorik
3
count <= count+1 when rising_edge(clock) ; 
4
countout <= to_integer(count)  when count(5)='0' else
5
              31-to_integer(count(4 downto 0));
6
PWM_0 <= '1' when count >= BREITE else '0';

meinst du vielleicht beim
1
countout<=to_integer(count)  when count(5)='0' else

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb:
> meinst du vielleicht beim

Nein, das ist kein Vergleich mit BREITE. <= ist eine Zuweisung.

Da drinnen
PWM_0 <= '1' when count >= BREITE else '0';
hast du den Vergleich >= mit BREITE.

Da solltest du statt count countount verwenden. Aber weil countout ein 
Integer ist und BREITE ein unsigned musst du BREITE zusätzlich zu einem 
Integer machen für diesen Vergleiche und nur dort.
to_integer(BREITE)

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Nein, das ist kein Vergleich mit BREITE. <= ist eine Zuweisung.

Danke das Notier ich mir gleich.
1
PWM_0 <= '1' when countout >= to_integer(BREITE) else '0';

Sieht nun so aus passt auch ohne Fehler.

Was wären nun die nöchsten Schritte die Schalter?

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb:
> Was wären nun die nöchsten Schritte die Schalter?

Ja genau. Bisher verwendest du BREITE. Also ersetze jetzt BREITE durch 
die Schalter und zwar für die PWM_0 - um die es bisher geht - die 
Schalter(4 downto 0).

Wenn du jetzt schalter(4 downto 0) mit countout vergleichen willst, dann 
ist das Problem, dass Schalter ein std_logic_vector ist und countout ein 
Integer. Du musst also schalter(4 downto 0) nach Integer wandeln für 
diesen einen Vergleich.

Das geht nicht auf einmal.

Zuerst machst du aus schalter(4 downto 0) einen unsigned.
Und dann aus dem unsigned einen Integer.

Hier als Beispiel mit anderen Namen:

signal vector: std_logic_vector(7 downto 0);

unsigned(vector) ist dann der vector nach unsigned gewandelt.

Und
to_integer(unsigned(vector))
ist das Ganze dann als Integer.

Nur dass du eben nicht vector(7 downto 0) sondern schalter(4 downto 0) 
hast.

Eine Übersicht über die Konvertierungen liefert das Bild dort:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Nur dass du eben nicht vector(7 downto 0) sondern schalter(4 downto 0)
> hast.

Muss ich aber dann ein neues Signal erzeugen für die Schalter und dort 
mit unsigned anfangen?

Habs mal gemacht sieht momentan so aus:
1
-- Signale hierher
2
 constant BREITE:  unsigned(4 downto 0):="01000"; -- das ist der Wert 8.
3
 signal count:     unsigned (5 downto 0) := (others=>'0');
4
 signal schalter0:   unsigned (4 downto 0) := (others=>'0');
5
 signal schalter1:   unsigned (9 downto 5) := (others=>'0');
6
 signal countout:  integer range 0 to 31;
7
8
  
9
begin
10
-- hier ungetaktete Kombinatorik
11
count <= count+1 when rising_edge(clock) ; 
12
countout <= to_integer(count)  when count(5)='0' else
13
              31-to_integer(count(4 downto 0));
14
PWM_0 <= '1' when countout >= to_integer(unsigned(schalter0)) else '0';
15
PWM_1 <= '1' when countout >= to_integer(unsigned(schalter1)) else '0';

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Nein.

Aber kannst du. Und dann kannst du dir das Signal wie countout auch 
gleich als Integer bauen. Das macht den Vergleich mit countout leichter 
weil das auch ein Integer ist.

Die Konvertierung kann man in eine Zeile schreiben. Also man kann 
mehrere Konvertierungen schachteln. Siehe:

to_integer(unsigned(vector))

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:
> Nein.
>
> Aber kannst du. Und dann kannst du dir das Signal wie countout auch
> gleich als Integer bauen. Das macht den Vergleich mit countout leichter
> weil das auch ein Integer ist.
>
> Die Konvertierung kann man in eine Zeile schreiben. Also man kann
> mehrere Konvertierungen schachteln. Siehe:
>
> to_integer(unsigned(vector))

Vermerk ich auch gleich aber würde das was ich grad eben gezeigt hab so 
passen?

von Gustl B. (-gb-)


Lesenswert?

signal schalter0:   unsigned (4 downto 0) := (others=>'0');
 signal schalter1:   unsigned (9 downto 5) := (others=>'0');

Das sind beides unsigned, kann man so machen, könntest aber auch gleich 
Integer nehmen.

PWM_0 <= '1' when countout >= to_integer(unsigned(schalter0)) else '0';
PWM_1 <= '1' when countout >= to_integer(unsigned(schalter1)) else '0';´

Da wandelst du etwas zuerst nach unsigned und dann nach Integer. Das 
macht keinen Sinn weil schalter0 und schalter1 schon unsigned sind. Die 
müsstest du nur noch nach Integer wandeln.

Und dann musst du irgendwie schalter0 und schalter1 mit den 
tatsächlichen Schaltern verbinden.

Damit schalter(4 downto 0) zu schalter0 und schalter(9 downto 5) zu 
schalter1 zugewiesen werden. Diese Verbindung fehlt noch inklusive 
Konvertierung.

Du hast
schalter : in  std_logic_vector(9 downto 0);
als Eingang. Das sind 10 Drähte. Und daraus willst du zwei Werte machen 
schalter0 und schalter1. Die oberen 5 Drähte schalter(9 downto 5) sollen 
zu dem Wert schalter1 werden und die unteren 5 Drähte schalter(4 downto 
0) sollen zu dem Wert schalter0 werden.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:
> signal schalter0:   unsigned (4 downto 0) := (others=>'0');
>  signal schalter1:   unsigned (9 downto 5) := (others=>'0');
>
> Das sind beides unsigned, kann man so machen, könntest aber auch gleich
> Integer nehmen.
>
> PWM_0 <= '1' when countout >= to_integer(unsigned(schalter0)) else '0';
> PWM_1 <= '1' when countout >= to_integer(unsigned(schalter1)) else '0';´
>
> Da wandelst du etwas zuerst nach unsigned und dann nach Integer. Das
> macht keinen Sinn weil schalter0 und schalter1 schon unsigned sind. Die
> müsstest du nur noch nach Integer wandeln.
>

Meinst du das So?
1
architecture rtl of PWM is
2
3
-- Signale hierher
4
 constant BREITE:  unsigned(4 downto 0):="01000"; -- das ist der Wert 8.
5
 signal count:     unsigned (5 downto 0) := (others=>'0');
6
 signal schalter0:   integer range 0 to 31;
7
 signal schalter1:   integer range 0 to 31;
8
 signal countout:  integer range 0 to 31;
9
10
  
11
begin
12
-- hier ungetaktete Kombinatorik
13
count <= count+1 when rising_edge(clock) ; 
14
countout <= to_integer(count)  when count(5)='0' else
15
              31-to_integer(count(4 downto 0));
16
PWM_0 <= '1' when countout >= schalter0 else '0';
17
PWM_1 <= '1' when countout >= schalter1 else '0';

> Und dann musst du irgendwie schalter0 und schalter1 mit den
> tatsächlichen Schaltern verbinden.
>
> Damit schalter(4 downto 0) zu schalter0 und schalter(9 downto 5) zu
> schalter1 zugewiesen werden. Diese Verbindung fehlt noch inklusive
> Konvertierung.
>
> Du hast
> schalter : in  std_logic_vector(9 downto 0);
> als Eingang. Das sind 10 Drähte. Und daraus willst du zwei Werte machen
> schalter0 und schalter1. Die oberen 5 Drähte schalter(9 downto 5) sollen
> zu dem Wert schalter1 werden und die unteren 5 Drähte schalter(4 downto
> 0) sollen zu dem Wert schalter0 werden.

Nun wir benutzen Quartus um unsere Programme auf einen FPGA zu laden und 
machen die Verbindungen mit den DIP Schalter auf dem Board.

von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb:
> Meinst du das So?

Jap.

Armin D. schrieb:
> Nun wir benutzen Quartus um unsere Programme auf einen FPGA zu laden und
> machen die Verbindungen mit den DIP Schalter auf dem Board.

Das meine ich nicht.

Ich meine schalter1 und schalter0 haben noch keinen Wert. Den musst du 
denen noch geben.

Und zwar hast du die 10 Schalter als Eingang:
schalter : in  std_logic_vector(9 downto 0);

Der Wert der
schalter(9 downto 5) soll schalter1
und der Wert der
schalter(4 downto 0) soll schalter0
zugewiesen werden.
Und zwar kombinatorisch immer. Wie auch deine anderen Zuweisungen.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Der Wert der
> schalter(9 downto 5) soll schalter1
> und der Wert der
> schalter(4 downto 0) soll schalter0
> zugewiesen werden.
> Und zwar kombinatorisch immer. Wie auch deine anderen Zuweisungen.

Also meinst du das so mit den Zahlenwerten?
1
-- Signale hierher
2
 constant BREITE:  unsigned(4 downto 0):="01000"; -- das ist der Wert 8.
3
 signal count:     unsigned (5 downto 0) := (others=>'0');
4
 signal schalter0:   integer range 0 to 31;
5
 signal schalter1:   integer range 32 to 63;
6
 signal countout:  integer range 0 to 31;

von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb:
> Also meinst du das so mit den Zahlenwerten?

Nein, das war vorher schon korrekt mit 0 to 31.

Du hast oben in der PWM.vhd die Zeile
schalter : in  std_logic_vector(9 downto 0);

Das sind 9 ... 0 also 10 Drähte/Bits. Die kommen rein. schalter(9 downto 
5) ist die obere Hälfte der 10 Bits und schalter(4 downto 0) die untere 
Hälfte.

Armin D. schrieb:
> signal schalter0:   integer range 0 to 31;
>  signal schalter1:   integer range 0 to 31;

Das sind beides Signale. Die haben bei dir erstmal keinen Wert, aber 
schalter1 soll ja immer, den Wert haben der mit den oberen 5 Schaltern 
eingestellt wurde und schalter0 soll immer den Wert haben der an den 
unteren 5 Schaltern eingestellt wurde.

Damit das so ist musst du die 10 Bits von
schalter(9 downto 0)
aufteilen in zwei Hälften
schalter(9 downto 5) und schalter(4 downto 0)
und diese dann den Signalen
schalter1 und schalter 0
zuweisen.

von Armin D. (okepasst)


Lesenswert?

Gustl B. schrieb:

> Damit das so ist musst du die 10 Bits von
> schalter(9 downto 0)
> aufteilen in zwei Hälften
> schalter(9 downto 5) und schalter(4 downto 0)
> und diese dann den Signalen
> schalter1 und schalter 0
> zuweisen.

Nun ja ich versteh zwar schon was du hiermit meinst dennoch weiss ich 
nicht wie ich das machen soll außer das ich, das hier, einfüge.

> signal schalter0:   unsigned (4 downto 0) := (others=>'0');
>  signal schalter1:   unsigned (9 downto 5) := (others=>'0');

wobei ich glaube das es nicht das ist was du mir sagen willst, denn wenn 
ich es so machen müsste würde ich wieder ein schritt zurück gehen.

von Gustl B. (-gb-)


Lesenswert?

Ah OK, dann erkläre ich mal genauer.

Deine .vhd sieht vom Konstrukt so aus:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity PWM is
  Port();
end PWM;

architecture rtl of PWM is

-- Signale hierher

begin

end;

Oben werden die Bibliotheken erklärt die verwendet werden.
Dann kommt die Erklärung der Ein- und Ausgänge in Port().
Dann kommt der Teil architecture und ab da beginnt die Beschreibung von 
dem Inhalt.
Bis zu begin werden nur Dinge deklariert aber da wird noch nichts 
gemacht. Also oberhalb von dem begin deklarierst du Signale, Konstanten, 
Typen, funktionen, ...
und unterhalb von dem begin, da verwendest du das Alles.

Mit

 signal schalter0:   integer range 0 to 31;
 signal schalter1:   integer range 0 to 31;

hast du diese beiden Signale korrekt deklariert.

Unterhalb von dem begin verwendest du die auch hier

PWM_0 <= '1' when countout >= schalter0 else '0';
PWM_1 <= '1' when countout >= schalter1 else '0';

aber du hast schalter1 und schalter0 noch keinen Wert zugewiesen. Das 
musst du noch machen.

Du kannst signalen direkt bei der Deklaration einen Initialwert 
mitgeben, also sowas hier

signal schalter0:   integer range 0 to 31:=15;

aber hier willst du ja, dass das Signal den Wert vom Eingang schalter 
übergeben bekommt.

Da gehört also unterhalb von begin noch eine Zuweisung für schalter1 und 
eine für schalter0 hin.

Sowas wie

schalter1 <= schalter( ... downto ..);
schalter0 <= schalter( ... downto ...);

Das passt aber noch nicht, denn schalter ist ein std_logic_vector und 
schalter1 und schalter0 sind beides Integer. Da musst du also noch 
Konvertierungen drum herum schreiben. Grob so:

schalter1 <= to_integer(unsigned(schalter( ... downto ..));

Da lasse ich dich jetzt etwas knobeln.
Dass das ruhig in Modelsim kompilieren und luies dir die Fehler durch 
wenn welche kommen. Sonst kannst du das auch simulieren.

Beitrag #6648175 wurde vom Autor gelöscht.
von Gustl B. (-gb-)


Lesenswert?

Armin D. schrieb im Beitrag #6648175:
>> Unterhalb von dem begin verwendest du die auch hier
>>
>> PWM_0 <= '1' when countout >= schalter0 else '0';
>> PWM_1 <= '1' when countout >= schalter1 else '0';
>>
>
> Ist also hier gemeint das:PWM_0 <= '1' when countout >= schalter0 else
> '0';
> PWM_1 <= '1' when countout >= schalter1 else '0';
> auch im beginn drin stehen muss oder nur das es verwendet wird?

Nein das kann so bleiben. Unterhalb von dem Begin verwendest du in den 
beiden Zeilen schalter1 und schalter0 aber du hast ihnen nie einen Wert 
zugewiesen. Und das musst du noch machen. Ebenfalls unterhalb von begin.

Armin D. schrieb im Beitrag #6648175:
> Danke das du dir heute soviel Zeit genommen hast mir das alles zu
> erklären das ist alles andere als selbstverständlich

Bitte!

von Armin D. (okepasst)


Lesenswert?

Dank dir vielmals für soviel Zeit die du dir heute genommen hast um mir 
zu helfen es ist nicht selbstverständlich und ich sehe es dir hoch an.

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.