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


von Arna (Gast)


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

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


Lesenswert?

1
 wait until rising_edge(TAST_W);
ist das selbe wie
1
 if rising_edge(TAST_W) begin
2
 :
3
 end if;

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

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


To be continued ;-)

von Nephilim (Gast)


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.

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


Lesenswert?

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


Zum eigentlichen Problem:
1
signal docount : std_logic := '0';
2
:
3
:
4
  process (clk) begin
5
    if (clk'event) and (clk='1') then
6
      if (docount ='1') then -- soll gezählt werden?
7
        delay_ctr<=delay_ctr+'1';
8
        if delay_ctr= "11111111111111111111111111" then
9
          delay_ctr <= (others => '0'); -- eigentlich unnötig, läuft sowieso über
10
          sigled <= sigled+'1'; -- LEDs hochzählen
11
        end if;
12
      else  -- Ruhezustand
13
        delay_ctr <= (others => '0');          
14
        sigled <= "00000000";
15
        clk_div <= '0';
16
    end if;
17
  end process;
18
19
  process (clk) begin
20
    if rising_edge(clk)  then
21
      if (TAST_W = '1') then -- taster W startet den Zähler
22
        docount <= '1';
23
      end if;
24
      if (TAST_C = '1') then -- Taster C stoppt und löscht den Zähler
25
        docount <= '0';
26
      end if;
27
    end if;
28
  end process;
Nur solltest du die asynchronen Eingänge (Taster) vorher noch 
einsynchronisieren.

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


Lesenswert?

Mit Integer lässt sich der Zähler noch schöner schreiben und lesen.
1
signal delay_ctr : integer rage 0 to 50000000 := 0; -- anpassen
2
signal docount : std_logic := '0';
3
signal Wsr : std_logic_vector(1 downto 0) := "00"; -- zum Einsynchronisieren der W-Taste
4
signal Csr : std_logic_vector(1 downto 0) := "00"; -- zum Einsynchronisieren der C-Taste
5
:
6
:
7
  process (clk) begin
8
    if (clk'event) and (clk='1') then
9
      if (docount ='1') then -- soll gezählt werden?
10
        if (delay_ctr=50000000) then -- anpassen
11
          delay_ctr <= 0;
12
          sigled <= sigled+'1'; -- LEDs hochzählen
13
        else 
14
          delay_ctr <= delay_ctr+1;
15
        end if;
16
      else  -- Ruhezustand
17
        delay_ctr <= (others => '0');          
18
        sigled <= "00000000";
19
        clk_div <= '0';
20
    end if;
21
  end process;
22
23
  process (clk) begin
24
    if rising_edge(clk)  then
25
      if (Wsr(1) = '1') then -- taster W startet den Zähler
26
        docount <= '1';
27
      end if;
28
      if (Csr(1) = '1') then -- Taster C stoppt und löscht den Zähler
29
        docount <= '0';
30
      end if;
31
    end if;
32
  end process;
33
34
  process (clk) begin -- Einsynchronisieren
35
    if rising_edge(clk)  then
36
       Wsr <= Wsr(0) & TAST_W; -- 2-Bit Schieberegister
37
       Csr <= Csr(0) & TAST_C;
38
    end if;
39
  end process;

Du kannst anstatt
1
  process (clk) begin
2
    if (clk'event) and (clk='1') then
3
       :
4
       :
5
    end if;
6
  end process;
auch so schreiben
1
  process begin
2
    wait until rising_edge(clk);
3
     :
4
     :
5
  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 ;-)

von Arna (Gast)


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

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.