FPGA - Programmlauf nach Tastendruck

Gast #1231458
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
Moderator (Firma: Titel) Persönliche Seite #1231481
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 ;-)
Gast #1231520
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.
Moderator (Firma: Titel) Persönliche Seite #1231546
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.
Moderator (Firma: Titel) Persönliche Seite #1231569
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 ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren