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.
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
ifpwmval>cntthenpwmout<='1';
2
elsepwmout<='0';
3
endif;
Oder der Zähler darf nur von 1..31 zählen und die Abfrage sieht dann so
aus:
1
ifpwmval<cntthenpwmout<='0';
2
elsepwmout<='1';
3
endif;
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:
Nach 12 Takten sind wir wieder bei cnt=0
Und zusammen mit obigem Vergleich:
1
ifpwmval>cntthenpwmout<='1';
2
elsepwmout<='0';
3
endif;
... 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.
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).
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
endif;
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.
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:
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 '&'.
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.
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?
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
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)
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
constantBREITE:unsigned(4downto0):="01000";-- das ist der Wert 8.
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
architecturertlofPWMis
2
3
-- Signale hierher
4
constantBREITE:unsigned(4downto0):="01000";-- das ist der Wert 8.
5
signalcount:unsigned(5downto0):=(others=>'0');
6
signalschalter0:integerrange0to31;
7
signalschalter1:integerrange0to31;
8
signalcountout:integerrange0to31;
9
10
11
begin
12
-- hier ungetaktete Kombinatorik
13
count<=count+1whenrising_edge(clock);
14
countout<=to_integer(count)whencount(5)='0'else
15
31-to_integer(count(4downto0));
16
PWM_0<='1'whencountout>=schalter0else'0';
17
PWM_1<='1'whencountout>=schalter1else'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
constantBREITE:unsigned(4downto0):="01000";-- das ist der Wert 8.
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.
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!