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
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
OK, oben der Code ist fehlerhaft. Nur mit Vergleichen > und < brauche ich eine zusätzliche Ausnahme für einen der Werte 31 oder 0.
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
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.
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
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.
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).
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
Kleine korrektur zu dem Code, da mir aufgefallen ist das es noch ein alter Stand war.
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...
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
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.
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.
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" )
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.
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
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.
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.
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.
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.
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
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.
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
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.
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.
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?
Welche? Teste das doch einfach, das dauert nur wenige Sekunden. Oder lade hier Code hoch, Testbench und deine PWM Komponente.
Oh Entschuldigung, in meiner Testbench hatte ich das noch nicht umbenannt. Im Anhang ist jetzt die richtige Testbench die die Komponente PWM korrekt einbindet.
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.
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.
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.
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
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)
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
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
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
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))
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?
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.
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.
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.
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; |
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.
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.
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.
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!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.