www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Suche Befehl eine einzelne Flanke


Autor: Kurz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich brauche eine Pinabfrage die nur dann eine if-Schleife aktiviert wenn 
der Port gerade auf 1 springt (Steigende Flanke oder Fallende das ist 
egal)

Dann soll die If-Schleife genau 1 Mal durchlanfen werden.

wenn  ich

process (PWM_Phase)
  begin
    if rising_edge(Plus_Taster)            then
      if PWM_Phase < PWM_Phase_MAX
      then
      PWM_Phase <= PWM_Phase + 7;
      end if;
    end if;

    if rising_edge(Minus_Taster  )
            then
      if PWM_Phase > 0
      then
      PWM_Phase <= PWM_Phase - 7;
      end if;
    end if;
  end process;


wenn ich das compeliere kommt die Fehlermeldung:

Error (10821): HDL error at testpwm.vhd(52): can't infer register for 
"PWM_Phase[0]" because its behavior does not match any supported 
register model

Von welchem Typ müssen die Variablen sein?

Oder was ist sonst der Fehler?


Vielleicht hat jemand ander Lösungsvorschläge wie ich eine Variable um 1 
erhöhen kann (Wenn ich einen Taster drücke und eventuell sogar halte).

Danke für die Hilfe

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du verwendest zwei unterschiedliche Clocks am selben FF. Soetwas kann 
nicht funktionieren, da es ein solches Element in keinem FPGA gibt.
Benutze einen einzigen Takt und Logik fuer die restliche Funktion.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die sensitivity list passt nicht zum Rest. Abgesehen davon ist das sehr 
schlechter Stil, weil du die Taster als Takt verwenden würdest. Falls 
die nicht entprellt sind, geht das katastrophal nach hinten los.

Besser: Taster evtl. entprellen und dann mit einer state machine (die 
mit dem Systemtakt arbeitet) auswerten.

Autor: Kurz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht wie ich das realisieren soll.

Mein Ziel ist es die Variable NUR um einen bestimmten Wert zu erhöhen. 
Wenn ich das Ganze mit dem CLOCK (66 MHz) laufen lasse kann ich ich den 
Taster gar nicht so schlell loslassen.

Hat jemand eine Idee?

Autor: Kurz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie meinst du das mit der state machine ?

Autor: Kurz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke es handelt sich um ein Standartproblem in VHDL eine Variable 
in Abhängigkeit vom Zustand (in dem Fall Taster) zu verändern.

Gibt es dafür Beispiele, die für VHDL - Einsteiger geeignet sind?

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In Hardware ausgedrückt nimmt man dafür zwei D-Flipflops am Systemtakt , 
die als 2-Bit-Schieberegister hintereinandergeschaltet sind, man kann 
das auch eine state-machine nennen mit 4 möglichen Zuständen.
Eine steigende Flanke wird mit UND-Verknüpfung der beiden Register 
erkannt. Genau dann wenn das erste schon umgeschaltet hat und das zweite 
noch nicht ist der Ausgang des UND high.

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem löst man, indem man verzögerte Signale für die 
Taster-signale erzeugt, und diese dann in einem geclockten Prozess 
abfragt. Zum Beispiel so (ohne Gewähr):
architecture rtl of ... is

signal plus_taster_delay : std_logic;
signal minus_taster_delay : std_logic;

begin

process (clk, reset)
  begin
    if(reset = '0') then
      plus_taster_delay  <= '0';
      minus_taster_delay <= '0';
    elsif(rising_edge(clk)) then
      plus_tasterr_delay <= plus_taster;
      minus_taster_delay <= minus_taster;
      if(plus_taster = '1' and plus_taster_delay = '0') then
        if PWM_Phase < PWM_Phase_MAX
        then
        PWM_Phase <= PWM_Phase + 7;
        end if;
      end if;
      if(minus_taster = '1' and minus_taster_delay = '0') then
        if PWM_Phase > 0 then
          PWM_Phase <= PWM_Phase - 7;
        end if;
      end if;
    end if;
end process;

end architecture rtl;

Autor: Kurz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ZUM BEITRAG VON     T.M. Gast:

ist in deinem Beispiel plus_taster_delay nicht immer '1' wenn 
plus_taster = '1'

das würde bedeuten (da Prozesse ja sequentiell ablaufen) dass die 
Abfrage:


IF (plus_taster ='1' and plus_taster_delay ='0')

nie erfüllt wäre


Oder täusche ich mich?

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Eine einfache Flankenerkennung reicht oft nicht, da die Signale von 
mechanischen Tastern prellen und keine sauberen Flanken liefern. Ich hab 
mal schnell ein Beispiel für 8 Taster zusammengehackt (gekürzt, 
Testbench im Anhang):
  -- Register
  signal state0, state1, state2: std_logic_vector(7 downto 0) := (others => '0');
  signal key_pressed_old: std_logic_vector(7 downto 0) := (others => '0');
  signal key_pressed: std_logic_vector(7 downto 0) := (others => '0');

  -- Taster mit langsamem Takt einlesen (3-Bit-Schieberegister je Taste)
  -- ce: clock enable mit ca. 1 kHz
  process(clk)
  begin
    if rising_edge(clk) and ce = '1' then
      state0 <= key_in;
      state1 <= state0;
      state2 <= state1;
    end if;
  end process;

  -- Mehrheitsentscheidung:
  -- 2x '1' => Taste geht in den Zustand "gedrückt"
  -- 2x '0' => Taste geht in den Zustand "nicht gedrückt"
  -- Vorteil: einzelne Pulse haben keine Auswirkung
  process(clk)
    variable state: std_logic_vector(2 downto 0);
  begin
    if rising_edge(clk) then
      for i in state0'range loop
        state := state2(i) & state1(i) & state0(i);
        case state is
          when "000" => key_pressed(i) <= '0';
          when "001" => key_pressed(i) <= '0';
          when "010" => key_pressed(i) <= '0';
          when "100" => key_pressed(i) <= '0';
          when others => key_pressed(i) <= '1';
        end case;
      end loop;

      key_pressed_old <= key_pressed;
    end if;
  end process;

  -- Ausgangssignale erzeugen:
  -- key_pressed_out: aktueller Zustand der Taste
  -- key_down_out: geht für 1 Takt auf '1' wenn Taste gedrückt
  -- key_up_out: geht für 1 Takt auf '1' wenn Taste losgelassen
  process(key_pressed, key_pressed_old)
  begin
    key_down_out <= key_pressed and (not key_pressed_old);
    key_up_out <= (not key_pressed) and key_pressed_old;
    key_pressed_out <= key_pressed;
  end process;

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Davon bin ich mal ausgegangen, dass die Dinger entprellt und 
synchronisiert wurden. Sonst stimme ich Andreas zu.

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auszug aus dem VHDL-Code von Andreas

  process(clk)
  begin
    if rising_edge(clk) and ce = '1' then


Dies ist meiner Meinung nach ein "gated Clock" welches man verhindern
sollte.
Besser wäre:

if rising_edge(clk) then
  if ce = '1' then
   ... Code hier
  end if;
end if;

So gibts nämlich in der Synthese ein getaktetes FF (synchrones Design).

Gruß Volker

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit rising_edge(clk and ce) wäre das ein Gated clock, so ist das nur 
eine kürzere Schreibweise für die zwei verschachtelten ifs. Mag 
allerdings sein dass ein paar veraltete Synthestools das nicht kapieren.

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich werde es morgen nochmals genau ansehen und einige ISE-Versionen 
dabei verwenden.

Und dann wäre zumindest dieser Thread (Beitrag 5 ff.) in Frage zu 
stellen.

Beitrag "Synthesefähiger Code"

Volker

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, so wie es ausschaut hat Andreas Recht. Sorry

Volker

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also QuartusII hat zumindest bis vor kurzem (6.x) auch noch ein gated 
clock draus gemacht.

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na dann doch lieber die verschachtelte Version.

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: noch besser (=robuster) wäre es eigentlich, nur umzuschalten 
wenn alle drei Register gleich sind, also:
      for i in state0'range loop
        state := state2(i) & state1(i) & state0(i);
        case state is
          when "000" => key_pressed(i) <= '0';
          when "111" => key_pressed(i) <= '1';
        end case;
      end loop;

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.