Forum: FPGA, VHDL & Co. PB-Taster entprellen mit Schiebregister


von 655432 (Gast)


Lesenswert?

Hallo,

ich verstehe folgenden Code zur Entprellung eines PB-Tasters nicht. Es 
handelt sich dabei um die DEBOUNCE-Funktion aus der Library UP1-Core von 
Quartus II.
1
 ENTITY debounce IS
2
  PORT(pb, clock_100Hz   : IN  STD_LOGIC;
3
     pb_debounced    : OUT  STD_LOGIC);
4
END debounce;
5
6
ARCHITECTURE a OF debounce IS
7
  SIGNAL SHIFT_PB     : STD_LOGIC_VECTOR(3 DOWNTO 0);
8
BEGIN
9
10
  -- Debounce clock should be approximately 10ms or 100Hz
11
  PROCESS
12
  BEGIN
13
      WAIT UNTIL (clock_100Hz'EVENT) AND (clock_100Hz = '1');
14
    -- Use a shift register to filter switch contact bounce
15
      SHIFT_PB(2 DOWNTO 0) <= SHIFT_PB(3 DOWNTO 1);
16
      SHIFT_PB(3) <= NOT PB;
17
      IF SHIFT_PB(3 DOWNTO 0)="0000" THEN
18
         PB_DEBOUNCED <= '0';
19
      ELSE 
20
          PB_DEBOUNCED <= '1';
21
      END IF;
22
  END PROCESS;
23
END a;

Mittlereile ist mir klar, dass das Signal pb um 40 ms verzögert wird. 
Nur wie das genau passiert (so ab der ersten If-Anweisung) ist mir nicht 
so ganz klar. Ich hoffe ihr könnt mir weiterhelfen.

von Jörg (Gast)


Lesenswert?

Im Prinzip wird so über die letzten 4 Taktzyklen getestet, ob die
Taste gedrückt ist (hier gedrückt gleich logisch 0). Ist das Signal
nicht stabil (z.B. ="0010","0110" etc.), dann wird '1' rausgegeben.
Eigentlich wird nur getestet, ob die Taste gedrückt wird, es wird
aber nicht das Loslassen entprellt!

Um z.B. zu testen, ob die Taste losgelassen wurde, muss die Zeile

  IF SHIFT_PB(3 DOWNTO 0)="0000" THEN

zu

  IF SHIFT_PB(3 DOWNTO 0)="1111" THEN

geändert werden. Für ein vollständiges Entprellen bräuchtest Du
also zwei Signale PB_DEBOUNCED_DOWN und PB_DEBOUNCED_UP.

von 655432 (Gast)


Lesenswert?

OK danke Jörg, dass hast du verständlich erklärt. Ich bin noch nicht fit 
in VHDL.

von gast (Gast)


Lesenswert?

Da  hätte ich auch mal eine Frage. Welche Technik würde man in der 
Praxis zum Entprellen eines Tasters verwernden.
a) Die oben beschriebene inkl. eines Clockdividers o.ä.
oder
b) Die Beschreibung mit einem runterzählenden Counter, der sich bei 
einer Störung zurücksetzt. Diesen kann man ja am normalen Clock 
betreiben, wenn man nur den Counter groß genug wählt. (50MHz bei meinem 
S3 Board)

bspw.
1
signal key_old, key_tmp: std_logic;
2
signal cnt: std_logic_vector(19 downto 0);
3
4
-- begin
5
 
6
deb:process(CLK_50)
7
begin
8
  if rising_edge(CLK_50) then
9
    key_tmp <= KEY_IN;
10
    if key_tmp /= key_old then
11
      cnt <= cnt-1;
12
    else
13
      cnt <= (others => '1');
14
    end if;
15
    if cnt=0 then
16
      key_old <= key_tmp;
17
    end if;
18
  end if;
19
end process deb;
20
KEY_OUT <= key_old;

Gibt es einen Grund, einer dieser Techniken den Vorzug zu geben, oder 
macht man das in der Praxis nochmal ganz anders?

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.