Forum: FPGA, VHDL & Co. Abschließen der Schleife trotz Interrupt!


von Chris K. (Gast)


Lesenswert?

Hallo Community,

ich setze mich gerade mit den Grundlagen von VHDL auseinander und bin 
bei meinen Programm auf ein Problem gestoßen, wofür ich leider keine 
Lösung finde, bestimmt ihr aber ;)

In meinem Programm werden jeweils 3 LEDS per while-Schleife angesteuert, 
welche hintereiander eingeschaltet und zum Schluß zusammen ausgeschaltet 
werden. Es funktioniert quasi wie ein Blinker nach rechts und nach 
links.
So der Interrupt ist der Schalter, der die Blinkrichtung ändert. Die 
Anforderung ist aber folgende, dass der angefangene Blinkzyklus 
abgeschlossen wird, d.h. wenn ich gerade bei der zweiten LED links bin 
und ich den Schalter umstelle, soll der "Links-Blink-Zyklus" noch 
abgeschlossen werden, bevor der andere Zyklus beginnt.

Oder in Kurzform: Wie erzwinge ich, dass die while Schleife 
abgeschlossen wird. Ich meine bei C ist das realtiv einfach möglich, 
aber ich weiß, wir sind hier nicht bei C.

Vielen Dank schonmal für eure Hilfe!

Chris

von Nobody (Gast)


Lesenswert?

Poste mal Deinen Code.

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


Lesenswert?

Eine While-Schleife in Hardware? Cool  :-o
Lass mal deinen Code sehen.

> In meinem Programm werden jeweils 3 LEDS per while-Schleife angesteuert,
Glaub mir: wenn du Hardware mit VHDL beschreibst, dann hast du weder ein 
Programm noch eine while-Schleife.

von Julian (Gast)


Lesenswert?

Könntest du das nicht mit nem endlichen Automaten (bei Fragezeichen im 
Gesicht hilft Wikipedia o.Ä.) machen, der nur im Anfangszustand den 
Taster (Status in FlipFlop gespeichert) abfragt?

von Nobody (Gast)


Lesenswert?

Jedenfalls wäre ein "while" selbst wenn es richtig angewandt wird nicht 
synthetisierbar. Also höchsten für Testbenches etc. gut. Es dient 
hauptsächlich dazu eine im vorhinein bekannte Anzahl gleichartiger 
Strukturen zu beschreiben.

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


Lesenswert?

> Könntest du das nicht mit nem endlichen Automaten machen...
Sollte das heißen:
Könntest du nicht endlich nen Automaten machen... ;-)

Kurz und gut:
Schlicht und einfach Alles, was in Hardware (FPGA und CPLD) 
nacheinander abläuft, wird auf so einen Automaten abgebildet werden 
müssen.

von Rene B. (themason) Benutzerseite


Lesenswert?

Vor allem ... einen Interrupt ? In VHDL ?!
Wie soll das denn gehen ?

von Mark B. (markbrandis)


Lesenswert?

Rene Böllhoff schrieb:
> Vor allem ... einen Interrupt ? In VHDL ?!
> Wie soll das denn gehen ?

Indem man einen Programmable Interrupt Controller synthetisiert? ;-)

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


Lesenswert?

Einen PIC?  Buoäh...  ;-)

von Rene B. (themason) Benutzerseite


Lesenswert?

>Indem man einen Programmable Interrupt Controller synthetisiert? ;-)

Öhm ja ... so gehts natürlich auch. Fehlt nur noch der Rest vom 
Prozessor. Aber wie Lothar schon meinte : Is ja eh nen PIC
duckundwech

von faustian (Gast)


Lesenswert?

Wenn es um irgendeine Form von CPU geht, ist das Stichwort 
Interruptmaskierung.

von Chris K. (Gast)


Lesenswert?

Es tut mir Leid für die jenigen, die Ihr Wissen zur Show stellen wollen, 
ich bin wie gesagt am Anfang von VHDL. Mit Interrupt meine ich einfach, 
eine Unterbrechung, was man ja aus meinen Text erschließen kann.

Und warum soll man keine "while loop" in einem prozess verwenden können? 
Bei klappt es aufjedenfall.

Hier der Code, für die Menschen, die einen wirklich helfen möchten:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
Use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;




entity Main is
  Port(
  clk: in std_logic ;               Schalter: in bit;
  LED: out std_logic_vector (5 downto 0));


end Main;

architecture Behavioral of Main is

signal led_intern: std_logic_vector (5 downto 0);
signal counter: std_logic_vector (25 downto 0);

begin

process (clk,Schalter,counter)

begin


if (rising_edge(clk)) then

counter <= counter + "01";

end if;


while Schalter = '1' loop

case counter(25 downto 24) is

          when "00" => led_intern <= "001000";
    when "01" => led_intern <= "011000";
    when "10" => led_intern <= "111000";
    when others => led_intern <= "000000";

end case;

end loop;


while not Schalter ='1' loop

case counter(25 downto 24) is

    when "00" => led_intern <= "000100";
    when "01" => led_intern <= "000110";
    when "10" => led_intern <= "000111";
    when others => led_intern <= "000000";

end case;



end loop;



end process;


LED <= led_intern;


end Behavioral;

von Chris K. (Gast)


Lesenswert?

Achso und das ganze hat nix mit ner CPU zu tun , sondern passiert auf 
dem XILINX Spartan 3 Board ;)

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


Lesenswert?

> Bei klappt es aufjedenfall.
Ja, was klappt denn?
Hast du das Synthetisiert?
Welche Warnungen hast du bekommen (Latch, kombinatorial Loop)?
Hast du dir den RTL-Schaltplan dazu schon mal angesehen?
Funktioniert das in realer Hardware?
Oder nur im Simulator?

> Es tut mir Leid für die jenigen, die Ihr Wissen zur Show stellen wollen,
> ich bin wie gesagt am Anfang von VHDL.
Jetzt sei doch nicht gleich so angesäuert... :-/
Sieh dir mal meine Lauflichtvarianten an. Eine davon ist garantiert 
total simpel auf deinen Anspruch abänderbar: 
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

von Chris K. (Gast)


Lesenswert?

@Lothar: Ja tut mir Leid, wir müssen uns das ganze in recht kurzer Zeit 
für das Testat auf den Schirm bringen und da ist man schonmal etwas 
schneller genervt, wenn man sieht, was man noch alles zu tun hat ;)

Die Synthese ergibt weder Fehler noch Warnungen, die habe ich alles 
behoben. Die Schaltung funktioniert auch wie sie soll. Das einzige 
Problem besteht darin, dass wenn man den Schalter umschaltet, die Leds 
sofort wechseln, sprich der eine Zyklus wird nicht beendet, was aber 
eine der Vorgaben ist.

Verstehst du mein Problem? ;)

von Rene B. (themason) Benutzerseite


Lesenswert?

Nimm die Witzelei nicht persönlich.
Es ist so das die meisten die Vorstellung haben das VHDL ein 
Programmablauf ist, bzw das man "normal" programmieren kann.
VHDL ist jedoch keine Programmiersprache sondern eine 
Beschreibungssprache. Du beshreibst das Verhalten deiner Hardware.
Die Hardware ist aber parallel, d.h. was du beschreibst läuft parallel 
ab und nicht sequentiell. Sequentielle Teile kann man zwar schon 
schreiben, aber diese sind dann eher für die Simulation als sogenannte 
Stimuli zum Testen deines Designs, aber eben nicht geeignet für die 
Synthese (sprich die Implementation auf dem FPGA selbst).
Wenn man sequentielles Verhalten haben will, so benötigt man entweder 
einen Zähler oder eine Statemachine. Nur damit lassen sich überhaupt 
erst Abläufe realisieren.
Und so gesehen macht eine Unterbrechung (eben der besagte Interrupt) bei 
parallel laufender Hardware keinen Sinn ;-P. Ist dann halt nur was 
schwierig zu verstehen was du meinst :-). Nimms nicht übel :-)

Zu deinem Problem

Wie besagt machen Schleifen in Hardware keinen Sinn.
Für dein Problem reicht eigentlich der Zähler aus.
Die Abfrage auf die Blinkrichtung kann man über ein if machen indem 
beide cases enthalten sind, die also theoretisch immer SOFORT 
umschalten.
Das if bezieht sich dann aber nicht auf die Schalterstellung, sondern 
ein weiteres Signal das den Schalterzustand übernimmt wenn der 
Blinkzyklus zuende ist.
Das wäre ein Lösungsvorschlag.

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


Lesenswert?

Deine loop lässt sich ganz leicht auch als if-Abfrage beschreiben.
Man macht keine kombinatorisch getakteten Prozesse. Besser: Aufteilen.
1
signal richtung : std_logic;
2
process (clk)
3
begin
4
  if (rising_edge(clk)) then
5
    counter <= counter + "01";
6
    if counter(25 downto 24)="00" then -- nur bei diesem Zählerzustand die Richtung ändern
7
      richtung <= Schalter;            -- Richtung soll gespeichert werden, deshalb im getakteten Prozess
8
    end if;
9
  end if;
10
end process;
11
12
process (richtung ,counter)
13
  if richtung = '1' then
14
    case counter(25 downto 24) is
15
    when "00"   => led_intern <= "001000";
16
    when "01"   => led_intern <= "011000";
17
    when "10"   => led_intern <= "111000";
18
    when others => led_intern <= "000000";
19
    end case;
20
  else
21
    case counter(25 downto 24) is
22
    when "00"   => led_intern <= "000100";
23
    when "01"   => led_intern <= "000110";
24
    when "10"   => led_intern <= "000111";
25
    when others => led_intern <= "000000";
26
    end case;
27
  end if;
28
end process;

von Chris K. (Gast)


Lesenswert?

@Lothar:

Vielen Dank für diese Antwort und deine Tipps! Es funktioniert alles 
genau so, wie es sein soll und man hat dabei noch was gelernt! ;)

von Chris K. (Gast)


Lesenswert?

Eine Frage noch Lothar, wegen dem Speichern der Richtung im getakteten 
Prozess. Ist es besser dort platziert oder MUSS es dort platziert sein? 
Und warum?

Danke für die Antwort im Vorraus ;)

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


Lesenswert?

> wegen dem Speichern der Richtung im getakteten Prozess.
Grundsätzlich Alles, was gespeichert werden soll, muß getaktet sein. 
Denn (grob gesagt) die einzigen Speicherglieder im FPGA sind Flipflops. 
Und das sind getaktete Bauteile.

Ein nicht getaktetes Speichergleid ist ein Latch, und das wirst du 
garantiert nur in sehr ausgewählten Fällen wirklich wollen...

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.