Forum: FPGA, VHDL & Co. Tastenentprellung


von Hilel (Gast)


Lesenswert?

Hallo zusammen.
Ich habe einige VHDL-Templates zur Tastenentprellung (u.a. debounce
circuit von ISE) getestet und festgestellt, dass sie alle leider nicht
viel taugen.
Daher möchte ich eine Zeitschleife einbauen, so dass nach Tastendruck
500 Millisekunden lang nichts passiert.
Weiss jemand wie sowas in VHDL geht oder hat vielleicht jemand ein
besseres Programm zur Tastenentprellung?
Danke im voraus.
P.S. Hier sind 2 Ausschnitte

PROG1:

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

--  Uncomment the following lines to use the declarations that are
--  provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;

entity entprell is
    Port ( D_IN : in std_logic;
           RESET : in std_logic;
           CLK : in std_logic;
           Q_OUT : out std_logic);
end entprell;

architecture Behavioral of entprell is
signal Q1, Q2, Q3 : std_logic;

begin
--  Provides a one-shot pulse from a non-clock input, with reset
process(CLK, RESET)
begin
  if (RESET = '1') then
    Q1 <= '0';
    Q2 <= '0';
    Q3 <= '0';
  elsif (CLK'event and CLK = '1') then
    Q1 <= D_IN;
    Q2 <= Q1;
    Q3 <= Q2;
  end if;
end process;

Q_OUT <= Q1 and Q2 and (not Q3);

end Behavioral;



PROG2:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
ENTITY entprell IS
  PORT( clkint: IN std_logic;
    rst: IN std_logic;
    button: IN std_logic;
    hit: OUT std_logic
      );
END entprell;

ARCHITECTURE myentprell OF entprell IS
  SIGNAL count: integer range 0 to 250000;
  SIGNAL buttonclk: std_logic;
  SIGNAL state: std_logic_vector(3 downto 0);
  BEGIN
    PROCESS(clkint, rst, count)
      BEGIN
        IF(rst='0') THEN
          count<=0;
          buttonclk <= '0';
        ELSIF(count=250000) THEN
          count<=0;
        ELSIF(clkint'event AND clkint='1') THEN
          if(count=0) THEN
            buttonclk <= not buttonclk;
        END IF;
        count<=count+1;
        END IF;
END PROCESS;
PROCESS(button, buttonclk, rst)
BEGIN
  IF(rst='0') THEN
    state<="1111";
  ELSIF(buttonclk'event AND buttonclk='1') THEN
  state(3 downto 1) <= state(2 downto 0);
  state(0) <= button;
  IF( state = "0000") THEN
    hit <= '1';
  ELSE
    hit <= '0';
END IF;
END IF;
END PROCESS;
END myentprell;

von Jörn (Gast)


Lesenswert?

ich würde es so probieren:

Mit dem ersten low/high oder high/low Übergang starte ich einen Zähler.
Ist der Abgelaufen übernehme ich den Zustand der Taste und verarbeite
sie weiter.

von Hilel (Gast)


Lesenswert?

Hallo Jörn.
Genau das war meine Idee.
Sobald die erste Flanke des Tasters erkannt wird, wird der Zähler
gestartet. Ist der abgelaufen, wird der Zusatnd der Taste (vor dem
Zählerstart) übernommen und am Ausgang soll ein Impuls gegeben werden.
Ich werde es mal versuchen in VHDL umzusetzen.
Danke Jörn

Gruss Hilel

von Thorsten (Gast)


Lesenswert?

> Mit dem ersten low/high oder high/low Übergang starte ich einen
> Zähler. Ist der Abgelaufen übernehme ich den Zustand der Taste und
> verarbeite sie weiter.

Macht es eigentlich einen Unterschied, ob ich den Zähler zuerst starte
und dann den Wert übernehme oder erst den Wert übernehme und dann den
Zähler starte? Im ersten Fall besteht doch die Gefahr, das der
übernommene Wert noch vom Prellen kommt, oder?

Thorsten

von Hilel (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen.
Ich habe den folgenden Code entdeckt und der ist prima.
Allerdings habe ich ein anderes Problem, wenn ich 2 unabhängige Taster
entprellen will (Schaltung s. Bild). Jeder Taster versorgt einen
BCD-Zähler mit Takten. Diese Takte werden gezählt und erscheinen als
BCD Zahl an der 7Seg.Anzeige. Soweit so gut.
Wird nur ein Taster entprellt, dann zählt der entsprechende Zähler
richtig (1,2,3...99 und nach 99 zurückgesetzt). Der andere Zähler
überspringt einige Zahlen, was selbstverständlich ist (keine
Entprellung).
Werden nun beide Taster entprellt, dann zählt der eine richtig und der
andere im Zweierschritt (2,4,8,...98,0,2 usw.).
Kann es jemand nachvollziehen?
Mit bestem Dank

Nun zum Code:

LIBRARY ieee;

USE ieee.STD_LOGIC_1164.all;

USE ieee.STD_LOGIC_UNSIGNED.all;



-- Short Name: Debc

ENTITY deb2 IS

PORT (

  Clk       : IN STD_LOGIC;

  Key       : IN STD_LOGIC;  -- active low input

  pulse     : OUT STD_LOGIC);

END deb2;

ARCHITECTURE Clean_pulse OF deb2 IS

  SIGNAL cnt       : STD_LOGIC_VECTOR (17 DOWNTO 0);

BEGIN

  PROCESS (Clk)

  BEGIN

    IF Key = '1' THEN

      cnt <= "000000000000000000";

    ELSIF (clk'EVENT AND Clk = '1') THEN

      IF (cnt /= "111111111111111111") THEN cnt <= cnt + 1; END IF;

    END IF;

    IF (cnt = "111111111111111110") AND (Key = '0') THEN pulse <=
'1'; ELSE pulse <= '0'; END IF;

  END PROCESS;

END Clean_pulse;

von Jörn (Gast)


Lesenswert?

@ Thorsten:

Ich würde behaupte, dass das von der verwendeten Taktfrequenz abhängt
mit der das System betrieben wird. Mit 50 Mhz ist der Wert des Tasters
vor und der Wert nach Ablauf des Zählers identisch. Ich bezweifle, dass
ein mechanischer Taster mit 50 Mhz prellt ;) Dessen Prellen wird sich im
Hz Bereich abspielen. Läuft die Schaltung aber auch nur mit ein paar
Hertz, kann es durch aus sein, dass der Wert vom Prellen stammt.
Ich benutzt meistens den den Wert nach Ablauf der Zeit.

von Peter D. (peda)


Lesenswert?

Mit 50MHz kann man auf keinen Fall entprellen !

Etwa 100Hz sind o.k.

Dann baut man mit 2 FFs einen Zähler 0..3 auf und noch ein FF zum
Speichern des entprellten Signals, fertig.

Nun noch einen 4. FF zur Flankenerkennung und schon ist man bei meinem
Beispielcode:

http://www.mikrocontroller.net/attachment.php/20758/Get8key4.c51

Sollte einfach für einen CPLD umzuschreiben sein.


Allerdings ist für so langsame Sachen ein Mikrokontroller wesentlich
effektiver und leistungsfähiger.

CPLDs haben nur dort einen Vorteil, wo man sehr sauschnell sein muß.

Ich nehme CPLDs daher nur als Zuarbeiter für Mikrokontroller, z.B.
Adreßdekodierung und Peripherie (GPIB-Controller).


Peter

von Hilel (Gast)


Lesenswert?

Wieso funktionniert es bei einem Taster einwandfrei und beim anderen
überhaupt nicht. Es handelt sich um dieselbe Entprellung. Und wieso
zählt der Zähler im Zweierschritt? Er zählt nur die geraden Zahlen
0,2,4,6,8...bis 98 und geht wieder auf 0. Er hat keine einzige ungerade
Zahl gezeigt. Es ist schon merkwürdig.
Hat jemand von Euch eine Idee oder einen besseren Vorschlag?
Es sollen 2 Taster unabhängig voneinander entprellt werden.

Vielen Dank

von Peter D. (peda)


Lesenswert?

Wieso fährt einer bei rot über die Kreuzung und überlebt aber ein
anderer ist tot ?

Einfach bei grün fahren, dann überlebt jeder.

Einfach richtig entprellen, dann geht jede Taste.


Es liegt in der Natur von Störeinflüssen, daß sie auftreten können,
aber nicht müssen.


Peter

von Hilel (Gast)


Lesenswert?

Hallo Peter.
Ich finde den Vergleich gar nicht angebracht.
Ich habe es nun so gelöst, dass die 50MHz runtergeteilt werden auf
100Hz. Dies reicht dann für eine Entprellung.

>>Es liegt in der Natur von Störeinflüssen, daß sie auftreten können,
aber nicht müssen.

Hier treten sie aber regelmässig auf. Das deutet auf einen Fehler hin.
Mir ging es einfach um diesen Fehler.

Gruss Hilel

von Peter D. (peda)


Lesenswert?

In Deinem Schaltplan gehen ja die 50MHz direkt auf die Entprellung.

Wie Du die ~100Hz erzeugst, ist egal, Hauptsache sie sind da (dürfte
bei 50MHz aber 19 FFs verbraten).

Wenn es trotzdem nicht geht, dann ist also Deine Entprellroutine
falsch.
Die 2-er Zählung könnte darauf hindeuten, daß Du das Entprellen beim
Loslassen "vergessen" hast.

Meine Routine entprellt beides, indem bei 4 aufeinanderfolgenden Takten
der gleiche Pegel erkannt werden muß, damit er übernommen wird, also für
mindestens 30..40ms.

Ich kenn mich mit VHDL nicht aus, sondern nur mit AND,OR,EXOR,NOT,
daher ist auch mein C-Programm so geschrieben (&,|,^,!).

Ich könnts Dir bei Interesse in Abel auf den GAL16V8 umschreiben.


Peter

von Hilel (Gast)


Lesenswert?

Hallo Peter.
Ich habe es schon hingekriegt.
Ich habe die 50 MHz auf 1MHz, dann auf 1KHz und am Schluss noch auf
100Hz runtergeteilt. Die Entprellung habe ich mit 3 FFs wie folgt
realisiert:
Q1 = D1  (D1: zu entprellende Taste)
Q2 = Q1
Q3 = Q2

Q_OUT = Q1 AND Q2 AND (NOT Q3)

<<Ich könnts Dir bei Interesse in Abel auf den GAL16V8 umschreiben.

Danke für Dein Angebot. Ich habe den Spartan3 Starter Kit von Digilent
und damit übe ich jetzt. Schon lange her, dass ich was mit FPGA gemacht
habe. Ausserdem hat die damalige (es sind schon 11 Jahre her) Software
(Workview) nur die  Schaltplaneingabe unterstützt.
Solche Aufgaben lassen sich natürlich mit uC viel einfacher lösen. Mir
geht es weniger um die Auswahl uC oder FPGA. Ich möchte einfach in die
Welt der VHDL-Sprache einsteigen und einige Programme mit dem Spartan3
Starter Kit testen.

Gruss Hilel

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

@Hilel,

"Q_OUT = Q1 AND Q2 AND (NOT Q3)"

Gut ist diese Entprellung nicht.
Beim Drücken entprellt sie 2-fach (2 High-Pegel nötig) und beim
Loslassen garnicht.

Anbei meine 4-fach-Entprellung in Abel.

Da ja ein Mikrokontroller sequenziell arbeitet, ein CPLD aber parallel,
habe ich einfach einige Zwischensignale definiert (*_TEMP), damits
gleich aussieht. Die werden aber alle sofort wieder rausoptimiert,
belegen also keine Ressourcen.


Peter

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Und hier die optimierten Gleichungen des Fitters.

Peter

von Max Müller (Gast)


Lesenswert?

Also mit dem zu entprellenden Eingang auf den Clock zu gehen ist
absoluter Murks!!!

Einfach Lösung:
2 Stufiges Schieberegister ( Zwei FF hintereinander)
Der CLK wird mit dem Sampleclock (Sinnvoller Weise um die =< 100HZ)
bedient.

Die beiden Ausgänge der Flipflops werden zusammen mit dem Ausgang eines
3. FF (Auch der selbe CLK) Mehrheits überprüft.

Das heisst, der Zustand der 2 mal vorhanden ist, wird ins 3 FF
übernommen.
Gleichung des 3. FF: FF3.D = FF1.Q & FF2.Q # FF2.Q & FF3.Q # FF1.Q &
FF3.Q


Der Ausgang des 3 FF ist entprellt.
Das ganze ist Synchron.
Metastabile Zustande können nur im ersten FF vorkommen.
Und auch noch Resourcen sparend, da kein Zähler zur konfimierung
benötigt wird.
Beide Richtungen sind entprellt.
Ein Glitch führt nicht zum umschalten.

Gruß

Max

von Peter D. (peda)


Lesenswert?

@Max,

"Also mit dem zu entprellenden Eingang auf den Clock zu gehen ist
absoluter Murks!!!"


wenn Du jetzt noch sagst, auf wen und was sich das beziehen soll ?

Ich sehe nämlich nirgends, daß jemand sowas gemacht hätte.


Peter

von Max Müller (Gast)


Lesenswert?

Stimmt!

Ich hab den ersten Eintrag nur schnell überflogen und bin bei
"ButtonCLK'event" davon ausgegangen, das das der Button selber ist.
Zumal im process darüber ein andere "CLK" für den Counter benützt
wurde . Somit 2 Clocks und das ist asynchrones Design.

Ich denke nicht, das du das in deiner Branche so machen würdest.
Nützt du eigentlich TMR umd die SEU Problematik in euren Geräten zu
umgehen, oder setzt ihr nichts RAM basierendes an PLD und FPGA's ein.

Gruß

Max

von Hilel (Gast)


Lesenswert?

Danke Peter, danke Max Müller für die Infos.
Ich habe beide Varianten getestet und in eine Schaltung mit 2
BCD-Zählern eingesetzt. Beide Entprellungen funktionieren.

@Peter.
Deine Entprellung in Abel habe ich mit einem Mealy-Automat (4 Zustände)
realisiert. Ich habe sie erstmal mit einem asynchr. Reset versehen und
getestet, ging leider nicht. Mit einem synch. Reset hat es dann
geklappt. Ich bin noch dabei herauszufinden, woran es liegt.

Jetzt habe ich insgesamt 3 unterschiedliche Methoden, um einen Taster
zu entprellen. Alle 3 Methoden wurden mit dem Spartan-Board erfolgreich
getestet.

Ich werde sie alle drei mit den unterschiedlichsten Tastern testen und
mich in Zukunft für eine entscheiden.

Ich danke Euch nochmal.

von Hilel (Gast)


Lesenswert?

Es hat sich erledigt mit dem asynchr. Reset.

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.