www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Taktflankenauswertung auf Buttons


Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich würde gerne wissen ob man grundsätzlich nur Taktflankenauswertungen 
auf Clocks vornehmen sollte, oder ob dies auch theoretisch auf bspw. 
Buttons angewendet werden kann.
Ich hatte einen kleinen Zähler aufgesetzt der auf die steigende Flanke 
des Buttons das Ergebnis erhöht, jedoch bekomme ich, abhängig von den 
ausgewählten Buttons, warnings oder errors.
Stellt sich mir halt die Frage ob man dies prinzipiell sein lassen 
sollte oder ob dies andere Gründe hat.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity toplevel is
  port(    RST : in std_logic;
      BTN2 : in std_logic;
      LED1 : out std_logic;
      LED2 : out std_logic;
      LED3 : out std_logic;
      LED4 : out std_logic);
end toplevel;

architecture Behavioral of toplevel is
  signal LED_TMP : unsigned(3 downto 0);

begin
  
  BTN_CNT_UP : process(BTN2, RST)
  begin  
    if(RST = '1') then
      LED_TMP <= "0000";
    elsif(BTN2'event and BTN2 = '1') then
      LED_TMP <= LED_TMP + 1;
    end if;
  end process;

  
  LED1 <= LED_TMP(0);
  LED2 <= LED_TMP(1);
  LED3 <= LED_TMP(2);
  LED4 <= LED_TMP(3);

end Behavioral;



Bei Nutzung von BTN1:

Warning:Place:619 - This design is using a Side-BUFG site due to 
placement constraints on a BUFG, DCM, clock IOB or the
   loads of these components. It is recommended that Top and Bottom BUFG 
sites be used instead of Side-BUFG sites
   whenever possible because they can reach every clock region on the 
device. Side-BUFG sites can reach only clock
   regions on the same side of the device and also preclude the use of 
certain Top and Bottom BUFGs in the same clock
   region.

Bei Nutzung von BTN2:

(Zwar kann man den Error mit NET "BTN2" CLOCK_DEDICATED_ROUTE = FALSE; 
beseitigen, jedoch schränke ich mich dann anderweitig ein)

Error: Place:1018 - A clock IOB / clock component pair have been found 
that are not placed at an optimal clock IOB /
   clock site pair. The clock component <BTN2_BUFGP/BUFG> is placed at 
site <BUFGMUX_X1Y10>. The IO component <BTN2> is
   placed at site <PAD287>.  This will not allow the use of the fast 
path between the IO and the Clock buffer. If this
   sub optimal condition is acceptable for this design, you may use the 
CLOCK_DEDICATED_ROUTE constraint in the .ucf
   file to demote this message to a WARNING and allow your design to 
continue. However, the use of this override is
   highly discouraged as it may lead to very poor timing results. It is 
recommended that this error condition be
   corrected in the design. A list of all the COMP.PINs used in this 
clock placement rule is listed below. These
   examples can be used directly in the .ucf file to override this clock 
rule.
   < NET "BTN2" CLOCK_DEDICATED_ROUTE = FALSE; >

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Stellt sich mir halt die Frage ob man dies prinzipiell sein lassen
> sollte
JA. So werden Flanken von irgendwelchen asynchronen Eingängen niemals 
abgefragt!
Ein ideales Anfängerdesign (und sowas mchst du offenbar) sieht so aus:
Genau 1 Takt (der kommt von einem Oszillator und hat so um 50MHz)
und genau 0 Resets.
Flanken von externen Signalen werden so ausgewertet, dass die erst mal 
einsynchronisiert werden und dann ein vorher-nachher Vergleich die 
Flanke ermittelt:
http://www.lothar-miller.de/s9y/categories/18-Flan...
Sieh dir mal die Lauflichterorgie auf meiner HP an:
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

> oder ob dies andere Gründe hat.
Du kannst nicht mit jedem x-beliebigen Pin auf ein Taktnetz (abhängig 
vom FPGA geht das mit Einschränkungen). Mit dem Aufheben der Forderung 
nach einem Taktnetz (CLOCK_DEDICATED_ROUTE = FALSE) erlaubst du den 
Tools, einen Takt von irgendwoher auf beliebigen Umwegen zu einem 
Flipflop zu verdrahten. Das wirst du einsehen: das geht gern mal ins 
Auge.

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten Dank soweit,

also ich hab mir dein Code für das Einsynchronisieren mal angeschaut und 
ist eigentlich auch gut verständlich.
Nun erhalte ich ja durch den Vorher, Nachhervergleich in sr(3) und sr(2) 
einen 1-Takt langen Ausschlag von rise oder fall. Ist es nun möglich auf 
diese beiden Signale das Attribut event anzuwenden da sie ja synchron 
zur clock laufen? Oder liegt ich da jetzt wieder falsch? Ist für mich 
noch ein bisschen schwammig das Ganze, weil " x'event and x = '1' " für 
mich lediglich ein Mittel war, irgendeine Taktflanke zu bestimmen. 
Wahrscheinlich fehlt mir da noch der Bezug zur Hardware.
Und wieso hast du den Vector sr 4 Bit breit gemacht? 2 Bit würden doch 
auch langen?
library ieee;
use ieee.std_logic_1164.all;

entity edge_detect is
  port (async_sig : in std_logic;
        clk       : in std_logic;
        rise      : out std_logic;
        fall      : out std_logic);
end;

architecture RTL of edge_detect is
begin
  process
    variable sr : std_logic_vector (3 downto 0) := "0000";
  begin
    wait until rising_edge(clk);
    -- Flanken erkennen
    rise <= not sr(3) and sr(2);
    fall <= not sr(2) and sr(3);
    -- Eingang in Schieberegister einlesen
    sr := sr(2 downto 0) & async_sig;
  end process;
end architecture;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guest schrieb:
> Und wieso hast du den Vector sr 4 Bit breit gemacht? 2 Bit würden doch
> auch langen?
Okok. Ich lasse mich auf 3 Bits herunterhandeln: 2 zum 
Einsynchronisieren und das 3. zur Flankenunterscheidung.

> Ist es nun möglich auf diese beiden Signale das Attribut event
> anzuwenden da sie ja synchron zur clock laufen?
> Oder liegt ich da jetzt wieder falsch?
Halten wirs wie bei Terminators: es kann nur EINEN geben. Gemeint ist 
damit der Takt. Wenn irgendwo ein 'event oder ein rising_edge() oder ein 
falling_edge() auftaucht, dann steht das in Idealfall immer das selbe 
Signal dabei.

>    variable sr : std_logic_vector (3 downto 0) := "0000";
Vergiss diese Anwendung von Variablen:
Mach Variablen niemals speichernd, du wirst damit (füher oder später) 
dein blaues Wunder erleben.
Dazu mehr im Beitrag "Variable vs Signal"

> Wahrscheinlich fehlt mir da noch der Bezug zur Hardware.
Kauf (oder leih) dir das Buch "VHDL-Synthese" von Reichardt/Schwarz. Da 
werden dir ein paar Lichtlein aufgehen...

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Okok. Ich lasse mich auf 3 Bits herunterhandeln: 2 zum
> Einsynchronisieren und das 3. zur Flankenunterscheidung.

Die Flankenunterscheidung wird doch in den Signalen rise und fall
abgelegt?

Aber gut, dann werd ich mich auf den EINEN beschränken. Stellt sich mir 
nur noch eine Frage. Die Flankenunterscheidung, z.B. rise bleibt ja 
einen ganzen Takt auf 1.
Letztendlich war es ja mein Ziel bei der Flanke aufwärts zu Zählen, so 
quasi in der Art:
(wobei BTN1_RISE die manuelle Flankenauswertung ist)
SET_OUTPUT : process(BTN1_RISE, CLK, RST)
  begin
    if(RST = '1') then
      LED_TMP <= "0000";
    elsif(BTN1_RISE = '1' and BTN1_RISE'event) then
      LED_TMP <= LED_TMP + 1;
    end if;
  end process;

Da es aber nur EINEN gibt, bleibt mir ja bestenfalls die folgende 
Möglichkeit, die aber auch nicht das gewünschte Ergebnis liefert
elsif(BTN1_RISE = '1') then

Mir fehlt also lediglich eine Möglichkeit nun, wie auch beim 'event, 
einmalig in den elsif Zweig bei einer Flanke einzusteigen.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal angenommen, du erzeugt dir einen Flankenimpuls von genau 1 Takt 
Dauer. Das Zählen der Flanken geht dann so:
SET_OUTPUT : process(CLK, RST)
   begin
     if(RST = '1') then           -- Achja, die lieben asynchronen Lehrbuchresets...
       LED_TMP <= "0000";
     elsif rising_edge(clk) then  -- es kann nur EINEN geben
        if(BTN1_RISE = '1') then  -- genau für 1 clk Zyklus aktiv
           LED_TMP <= LED_TMP + 1;
        end if;
     end if;
  end process;

Zum Thema "Reset" gabs hier im 
Beitrag "Xilinx und die Resets" schon mal ein paar 
tiefergehende Betrachtungen, die in der gesamten Länge incl. der 
weiterführenden Links einen Blick wert sind.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.