Hallo, ich bin gerade dabei mit VHDL ein bisschen rumzuspielen. Dazu habe ich mir ein Buch gekauft und auch schon einige einfache Beispiele simuliert. Jetzt habe ich den Lötkolben ausgepackt und eine CPLD von Xilinxs auf eine kleine Platine gelötet mit 3 Tastern und 3 LEDs. Funktioniert so weit so gut. Ich habe ein paar kleine Tests gemacht und kam dann auf die Idee, dass bei Tasterdruck eine LED angehen soll und bei erneuten Druck wieder aus. Tastenentprellung ist mir erstmal egal, den Effekt müsste man ja trotzdem sehen. Wie bekommt man so was hin? Ich bekomme nur immer Fehlermeldungen, das ich irgendwelche Latches generiert habe (bzw Warnungen)... oder geht das nicht so einfach? Mein erster Gedanke war dieser hier... (alle anderen haben ihren Zweck auch nicht erfüllt :-D) Wenn TASTER(0) sich ändert, also von 0 auf 1 springt oder umgekehrt wird der Prozess ausgelöst .... hab nur die "interesanten" Codezeilen rauskopiert: type STATE_TYPE is (LED_ON, LED_OFF); signal STATE : STATE_TYPE := LED_OFF; ...... process (TASTER(0),STATE) begin if (STATE = LED_OFF) then STATE <= LED_ON; else STATE <= LED_OFF; end if; end process; with STATE select LED(4) <= '0' when LED_ON, '1' when others; achja benutze Xilinx Webpack 11 Bitte um HILFE :-) Danke Grüße balou
also das sollte funktionieren process (TASTER(0)) begin if rising_edge(TASTER(0)) then if (STATE = LED_OFF) then STATE <= LED_ON; else STATE <= LED_OFF; end if; end if; end process; LED(4) <= '0' when LED_ON else '1';
Cool Danke funktioniert wirklich! Ich hatt es ungefähr so probiert... process (TASTER(0)) begin if (TASTER(0)'event) then .... dann gabs aber einen Error line 64: unsupported Clock statement. Ich dachte das wäre so ziemlich das gleiche??? Grüße balou
Hm so funktioniert es ... process (TASTER(0)) begin if (TASTER(0)'event and TASTER(0) = '1') then if (STATE = LED_OFF) then ...... warum darf man nicht TASTER(0)'event alleine verwenden???? Danke euch!! super Forum Grüße balou
balou schrieb: > warum darf man nicht TASTER(0)'event alleine verwenden???? Weil dies bedeuten würde, dass die Ausgangssignale auf beide Flanken reagieren, also wenn Taster(0) sich von 0 auf 1 ODER von 1 auf 0 ändert. Die normalen Flip Flips in einem CPLD oder FPGA reagieren aber nur auf eine Flanke, also entweder aufsteigen oder abfallen, deshalb muss man noch TASTER(0)'event and TASTER(0) = '1' schreiben. Das bedeutet, dass das Signale Taster(0) nun auf '1' ist und sich gerade geändert hat (also kam es von 0 auf 1). Du solltest Dir aber angewöhnen, "rising_edge(Taster(0)) zu schreiben, das ist das selbe und besser lesbar.
Und einen Taster als Clock verwenden, ist -- gleich ob in einem CPLD, FPGA oder ASIC -- mehr als mutig.
Hallo... Danke für euer Antworten, hat mir sehr weiter geholfen. @ der mechatroniker "Und einen Taster als Clock verwenden, ist -- gleich ob in einem CPLD, FPGA oder ASIC -- mehr als mutig." Wie würdest du das dann implementieren? Wenn ich eine Flanke eines Tasters abfrage, warum ist das dann gleich ein Clock? grüße balou
Man taktet das über ein Schieberegister zu seiner Clockdomäne ein und schaut ob ein Wechsel von 0 auf 1 im Schieberegister steht.
>warum ist das dann gleich ein Clock? Immer wenn du "event" oder "rising_edge" verwendest, wird das entsprechende Signal an den Takteingang der Flipflops gelegt. Ein Takt ist nicht einfach nur ein Signal, sondern ein Riesiges Netzwerk von sehr schnellen Verbindungen zu allen FF. Da dein "Tastentakt" keinen Definierten Zeitlichen Bezug hat, kann es zu Metastabilitäten kommen. In einem Design sollte man nur einen Takt verwenden. >Wie würdest du das dann implementieren? Einen Counter den Systemtakt Zählen lassen, wenn die Taste Gedrückt ist. Wird sie Losgelassen den Counter resetten. Hat der Counter den Wert x erreicht, dann die Led umschalten. Das Loslassen der Taste musst du natürlich ähnlich lösen.
Hallo, habe leider nicht so ganz verstanden was du gesagt hast. Was genau hat hier ein Schieberegister zu tun? Ich habe den Code nun mal abgeändert, in der Hoffnung das getan zu haben was du meintest :-D Hoffe ihr könnt ihr noch ein paar Tips geben? Relevanter Codeteil... Rest im Anhang.
1 | process (TASTER(0), CLK) |
2 | type TASTER_STATE_TYPE is (TASTER_PRESSED, TASTER_RELEASED); |
3 | variable TASTER_STATE : TASTER_STATE_TYPE := TASTER_RELEASED; |
4 | begin
|
5 | if rising_edge(CLK) then |
6 | if (TASTER(0) = '0') and (TASTER_STATE = TASTER_RELEASED) then |
7 | if (STATE = LED_OFF) then |
8 | STATE <= LED_ON; |
9 | else
|
10 | STATE <= LED_OFF; |
11 | end if; |
12 | TASTER_STATE := TASTER_PRESSED; |
13 | elsif (TASTER(0) = '1' and (TASTER_STATE = TASTER_PRESSED)) then |
14 | TASTER_STATE := TASTER_RELEASED; |
15 | end if; |
16 | end if; |
17 | end process; |
18 | |
19 | LED(4) <= '0' when (STATE = LED_ON) else '1'; |
Deine Beschreibung wird bei einer angemessenen Taktfrequenz einfach das Prellen des Tasters an die LED weitergeben. Tasterabfragen gehen anders: http://www.lothar-miller.de/s9y/categories/5-Entprellung Und, voila: da ist es, das Scheiberegister ;-) So wie hier wäre das Verhalten deiner Beschreibung übrigens ganz ohne Prozess und ohne signifikante Funktionseinschränkung kürzer beschrieben:
1 | LED(4) <= not TASTER(0) when rising_edge(CLK); |
BTW: Dein Prozess oben ist nur auf CLK sensitiv. TASTER(0) ist unnötig. Als Tipp: du brauchst in deinem ersten viertel VHDL-Jahr garantiert (!!!!) keine Variable. Sicher nicht.
Hey Danke für deine ausführliche Antwort "So wie hier wäre das Verhalten deiner Beschreibung übrigens ganz ohne Prozess und ohne signifikante Funktionseinschränkung kürzer beschrieben: ........" Dann wird die LED aber doch nur ausgeschaltet solange der Taster gedrückt wurde. Quasi so wie ich es mit den anderen LEDs testweise auch gemacht habe. Ich wollte ja, dass wenn ich einmal drücke die LED anbleibt auch wenn ich loslasse, bis ich noch mal drücke. "BTW: Dein Prozess oben ist nur auf CLK sensitiv. TASTER(0) ist unnötig. Als Tipp: du brauchst in deinem ersten viertel VHDL-Jahr garantiert (!!!!) keine Variable. Sicher nicht." Vielen Dank für die Hinweise. Kann ich als blutiger Anfänger gebrauchen! Hatte das "Gefühl" Variablen könnten manchmal praktisch sein. Warum sollte man diese nicht verwenden? Ich hätte dies also besser außerhalb des processes als Signal definiert? Mit dem Prellen war mit klar. Wollte erstmal die Funktion des "Speicherns" hinbekommen. Das andere war mir noch zu aufwenig. Danke für deine Codebeispiele die werde ich morgen mal durchschauen... Grüße
> Dann wird die LED aber doch nur ausgeschaltet solange der Taster > gedrückt wurde. Richtig, du willst ja die LED mit jedem Tastendruck toggeln... :-o Also brauchst du 1. eine zuverlässige Flankenerkennung für den Taster und dann kannst du 2. mit der erkannten Flanke die LED toggeln. > Hatte das "Gefühl" Variablen könnten manchmal praktisch sein. Warum > sollte man diese nicht verwenden? Such einfach mal hier im Forum nach dem Stichwort Variable und du findest allgemein Probleme mit den Dingern, spätestens, wenn sie Speichernd sein sollen (Zähler, Zustände, Scheiberegister...). Mehr dazu im Beitrag "Verständnisproblem: Variablen in Prozessen" und im Beitrag "Re: VHDL - UP / DOWN 3-Bit Zählerproblem" und recht ausführlich im Beitrag "Variable vs Signal".
Hallo Lothar Miller, ich habs noch mal versucht und einfach einen kleinen Counter eingebaut der per Tastendruck umschaltbar hoch oder runter zählen kann. Wäre Klasse wenn du noch mal drüber schaun könntest ... Kommentare erwünscht :-D
Sieht zwar stellenweise noch etwas verworren aus, passt aber schon mal
vom Grundkonzept her...
Insbesondere sollte ein gespeichertes Eingangsbit nicht gerade STATE
heißen, State hört sich irgendwie nach mehr an...
Ob es tatsächlich funktionieren kann, sagt dir eine
Verhaltenssimulation.
> process (CLK, STATE)
STATE ist hier unnötig, weil das Ergebnis des Prozesses nur von CLK
abhängt.
Den Teiler für die Sekunde solltest du ausserhalb machen, dann kannst du
das Sekunden-Flag öfeter mal verwenden:;
1 | process begin -- Vorteiler |
2 | wait until rising_edge(CLK); |
3 | OneSecond <='0'; |
4 | if (TIMER_COUNTER = XTAL - 1) then -- TIMER_COUNTER erzeugt Sek. Takt |
5 | TIMER_COUNTER <= 0; |
6 | OneSecond <='1'; |
7 | else
|
8 | TIMER_COUNTER <= TIMER_COUNTER + 1; |
9 | end if; |
10 | end process |
11 | |
12 | process begin -- Zähler |
13 | wait until rising_edge(CLK); |
14 | if OneSecond='1' then |
15 | case DIRECTION is |
16 | when '0' => |
17 | if (COUNTERX = 63) then -- Überlauf |
18 | COUNTERX <= 0; |
19 | else
|
20 | COUNTERX <= COUNTERX + 1; |
21 | end if; |
22 | when others => |
23 | if (COUNTERX = 0) then -- Überlauf |
24 | COUNTERX <= 63; |
25 | else
|
26 | COUNTERX <= COUNTERX - 1; |
27 | end if; |
28 | end case; |
29 | end if; |
30 | end process; |
31 | |
32 | process begin -- irgendwas anderes, das im Sekundentakt ablaufen soll |
33 | wait until rising_edge(CLK); |
34 | if OneSecond='1' then |
35 | :
|
36 | end if; |
37 | end process; |
Hallo, vielen Dank für deine Mühe und Kommentare. Habe viel gelernt.Verworren kam mir das auch vor, aber Tagesziel erreicht :-D Werde sicher am Wochenende noch ein bisschen weiter rumspielen :-D Funktionieren tut es. Habe ich gleich auf der Hardware ausgeführt. Dann habe ich mir zum Spaß mal eine Testbench erstellt und mit ModelSIM (die kostenlose Starter Version) ein bissel rum probiert. Hat zwar etwas länger gedauert ging aber mit Hilfe des Tutorial von denen recht gut. Gibt es da irgend ein Schema um eine VHDL Datei wirklich zu testen. Ich habe einfach mal ein paar Signale rein geschmissen und geschaut, ob das rauskommt was ich erwarten würde (bzgl Zählrichtung). Es ist ja anscheinend sehr wichtig zu simulieren. Gibt es irgendeinen Grund warum du Prozesse ohne sensity list verwendest ? Oder ist das ehr eine Geschmacksfrage? Nochmals vielen Dank!
balou schrieb: > > Gibt es irgendeinen Grund warum du Prozesse ohne sensity list verwendest > ? Oder ist das ehr eine Geschmacksfrage? Wenn man keine sensitivity List in getakteten Prozessen hat, kann man auch keine Signale zu viel oder zu wenig reintun ;)
>> Es ist ja anscheinend sehr wichtig zu simulieren. Mit einer Verhaltenssimulation kannst du wenigstens mal feststellen, ob dein Design prinzipiell funktionieren wird. Ob dann noch irgendwelche Probleme an Taktdomänenübergängen sind, findest du aber erst in der realen Hardware heraus... > Wenn man keine sensitivity List in getakteten Prozessen hat, kann man > auch keine Signale zu viel oder zu wenig reintun ;) Und man schafft es auch nicht, irgendwelche Quasi-Concurrent-Beschreibungen getaktet aussehen zu lassen. Die nfolgende Beschreibung wird in der Simulation so aussehen, wie wenn dataout vom Takt abhinge:
1 | process (clk) begin |
2 | if rising_edge(clk) then |
3 | : -- hier passiert jetzt einiges |
4 | end if; |
5 | dataout <= datain; -- und dann kommt noch eine ungetaktete Zuweisung |
6 | end process; |
Der Synthesizer wird aber einfach eine Verbindung zwischen datain und dataout machen, und das mit einer Warnung bekanntgeben. Dieser Prozess dagegen ist komplett getaktet:
1 | process begin |
2 | wait until rising_edge(clk); |
3 | : -- hier passiert jetzt einiges |
4 | dataout <= datain; -- und dann kommt noch eine getaktete Zuweisung |
5 | end process; |
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.