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
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 ;-)
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.
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.
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 ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.