www.mikrocontroller.net

Forum: FPGA, VHDL & Co. FPGA - Programmlauf nach Tastendruck


Autor: Arna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe ein für mich aktuell nicht zu lösendes Problem. Obwohl 
vermulich Trivial.

Es soll nach einem Tastendruck eine bestimmte Aktion ausgeführt 
werden, solange, bis eine weitere Taste gedrückt wird.
Diese Aktion ist dann wiederrum vom Systemclock abhängig.

Egal, welche Methode ich bisher versucht habe, es klappte nicht so, wie 
es sollte.

Zum Test habe ich ein einfaches Beispiel genommen:
wenn am FPGA die Taste (TAST_W) gedrückt wird, soll er anfangen und 
hochzählen, die LEDs (8Stück) sollen entsprechend leuchten. Wenn eine 
Reset-Taste (TAST_C) gedrückt wird, sollen die LEDs auf 00000000 
rückgesetzt werden und aufgehört werden zu zählen.

Zählen und Leuchten klappt ;) . Aber dass der FPGA nach dem 
Tastendruck, also auch, nachdem ich die Taste dann wieder loslasse 
weitermacht, bis ich z.B. eine andere Taste drücke, das klappt nicht.

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

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

entity Logic is
Port (CLK : in bit;
  TAST_C, TAST_W: in std_logic;      -- Taster
  LED  : out std_logic_vector(7 downto 0));   -- LED
end Logic;

architecture Tasten of Logic is
signal sigled : std_logic_vector (7 downto 0):= "00000000";
signal delay_ctr : std_logic_vector(25 downto 0) := 
"00000000000000000000000000";
signal clk_div   : std_logic;
signal clk_flank   : std_logic;

delay: process (clk, TAST_C)        -- nur damit ich das Zaehlen auch 
sehe
  begin
    if (TAST_C = '1') then          -- c-Taste = reset
    delay_ctr<="00000000000000000000000000";
    elsif (clk'event) and (clk='1') then
      delay_ctr<=delay_ctr+"00000000000000000000000001";
     if delay_ctr="11111111111111111111111111" then
        delay_ctr<="00000000000000000000000000";
      clk_div <= '1';
    else
      clk_div <= '0';
      end if;
    end if;
  end process delay;

----------------------------------------------------------------------
--ab hier poste ich jetzt mal drei versuchte Varianten, wobei das nicht 
alle sind
--Variante 1:
P_LED: process (clk_div, TAST_C, TAST_W)
begin
  if (TAST_C = '1') then
    sigled <= "00000000";
  elsif (TAST_W = '1') then
    if (clk_div'event) and (clk_div='1')  then
      sigled <= sigled + 1;
    end if;
  end if;
end process P_LED;

-- => solange Taste gedrückt wird, wird gezählt

----------------------------------------------------------------------
-- Variante 2
flanke: process (clk_div, TAST_W)
begin
  if (clk_div'event) and (clk_div='1') then
    if (TAST_W ='1') then
      clk_flank <= '1';
    else
      clk_flank <= '0';
    end if;
  end if;
end process flanke;

P_LED: process (clk_flank, TAST_C, TAST_W)
begin
  if (TAST_C = '1') then
    sigled <= "00000000";
  elsif (clk_flank'event) and (clk_flank='1') then
    sigled <= sigled + 1;
  end if;
end process P_LED;

-- => für jedes +1 muss Taste gedrückt werden

----------------------------------------------------------------------
-- Variante 3
P_LED: process (clk_div, TAST_C, TAST_W)
begin
  wait until rising_edge(TAST_W);
    if (clk_div'event) and (clk_div='1') then
      sigled <= sigled + 1;
    end if;
end process P_LED;

-- => geht nicht: "statement WAIT not allowed in a process with a 
sensitivity list"
-- (auch wenn ich die Zeile mit clk_div'event... weglasse)

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

Wo bitte ist mein Denkfehler? Wie muss es richtig lauten?
Danke und Grüße
Arna

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 wait until rising_edge(TAST_W);
ist das selbe wie
 if rising_edge(TAST_W) begin
 :
 end if;

Und wenn du also schreibst
process (clk_div, TAST_C, TAST_W)  --- überdefiniert!!!!
begin
  wait until rising_edge(TAST_W);
    if (clk_div'event) and (clk_div='1') then
      sigled <= sigled + 1;
    end if;
end process;

ist das das selbe wie
process (clk_div, TAST_C, TAST_W)  --- überdefiniert!!!!
begin
  if rising_edge(TAST_W) begin
    if rising_edge(clk_div) then
      sigled <= sigled + 1;
    end if;
  end if;
end process;
Und das das nicht geht, ist dir klar?


To be continued ;-)

Autor: Nephilim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du darst nicht einfach nur den zustand von TAST_W oder die Flanke an 
sich auswerten, sondern die Signaländerung musst du als Wert speichern 
also ein flipfop baun, welches diesen wert dann auch speichert solange 
bis du die reset-taste drückst und dein zählprozess ist dann von diesem 
gespeicherten wert abhängig.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
signal delay_ctr : std_logic_vector(25 downto 0) := "00000000000000000000000000";
:
:
      delay_ctr<=delay_ctr+"00000000000000000000000001";
liest und schreibt sich schöner so:
signal delay_ctr : std_logic_vector(25 downto 0) := (others => '0');
:
:
      delay_ctr<=delay_ctr+'1';


Zum eigentlichen Problem:
signal docount : std_logic := '0';
:
:
  process (clk) begin
    if (clk'event) and (clk='1') then
      if (docount ='1') then -- soll gezählt werden?
        delay_ctr<=delay_ctr+'1';
        if delay_ctr= "11111111111111111111111111" then
          delay_ctr <= (others => '0'); -- eigentlich unnötig, läuft sowieso über
          sigled <= sigled+'1'; -- LEDs hochzählen
        end if;
      else  -- Ruhezustand
        delay_ctr <= (others => '0');          
        sigled <= "00000000";
        clk_div <= '0';
    end if;
  end process;

  process (clk) begin
    if rising_edge(clk)  then
      if (TAST_W = '1') then -- taster W startet den Zähler
        docount <= '1';
      end if;
      if (TAST_C = '1') then -- Taster C stoppt und löscht den Zähler
        docount <= '0';
      end if;
    end if;
  end process;
Nur solltest du die asynchronen Eingänge (Taster) vorher noch 
einsynchronisieren.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Integer lässt sich der Zähler noch schöner schreiben und lesen.
signal delay_ctr : integer rage 0 to 50000000 := 0; -- anpassen
signal docount : std_logic := '0';
signal Wsr : std_logic_vector(1 downto 0) := "00"; -- zum Einsynchronisieren der W-Taste
signal Csr : std_logic_vector(1 downto 0) := "00"; -- zum Einsynchronisieren der C-Taste
:
:
  process (clk) begin
    if (clk'event) and (clk='1') then
      if (docount ='1') then -- soll gezählt werden?
        if (delay_ctr=50000000) then -- anpassen
          delay_ctr <= 0;
          sigled <= sigled+'1'; -- LEDs hochzählen
        else 
          delay_ctr <= delay_ctr+1;
        end if;
      else  -- Ruhezustand
        delay_ctr <= (others => '0');          
        sigled <= "00000000";
        clk_div <= '0';
    end if;
  end process;

  process (clk) begin
    if rising_edge(clk)  then
      if (Wsr(1) = '1') then -- taster W startet den Zähler
        docount <= '1';
      end if;
      if (Csr(1) = '1') then -- Taster C stoppt und löscht den Zähler
        docount <= '0';
      end if;
    end if;
  end process;

  process (clk) begin -- Einsynchronisieren
    if rising_edge(clk)  then
       Wsr <= Wsr(0) & TAST_W; -- 2-Bit Schieberegister
       Csr <= Csr(0) & TAST_C;
    end if;
  end process;

Du kannst anstatt
  process (clk) begin
    if (clk'event) and (clk='1') then
       :
       :
    end if;
  end process;
auch so schreiben
  process begin
    wait until rising_edge(clk);
     :
     :
  end process;



Ein Tipp:
Sieh dir mal das numeric_std package an. Das solltest du anstelle der 
STD_LOGIC_ARITH und STD_LOGIC_UNSIGNED nehmen. Die Vorteile kannst du 
hier im Forum suchen oder ergoogeln ;-)

Autor: Arna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die ausführlichen Antworten, hat mir sehr weitergeholfen, auch 
die kleinen Anmerkungen, wie einiges besser zu gestallten ist.

Grüße
Arna

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.