Schlechte synchrone Beschreibung - einfaches VHDL-Programm

Ich versuche, ein einfaches VHDL-Programm zu erstellen, das darin besteht, einen std_logic_vector bei jedem Drücken von Taste A um eins zu erhöhen. Wenn Knopf B gedrückt wird, sollte der Wert zurückgesetzt werden.

Meine Idee war, es so zu machen

entity simple is
    Port ( A : in std_logic;
           B : in std_logic;
           CLK : in std_logic;
           debug : out std_logic_vector (7 downto 0));
end simple;

architecture Behavioral of simple is
    signal state: std_logic_vector(7 downto 0) := "00000000";
begin

   increment: process(state, A, B)
    begin
        if (B'event and B = '1') then 
            state <= "00000000";
        end if;
        if (A'event andA = '1') then 
            state <= std_logic_vector(unsigned(state)+1);
         end if;
    end process;


    led_debug: process(CLK)
    begin
        debug <= state;
    end process;    

end Behavioral;

Das Problem ist, dass ich einen Fehler erhalte - Schlechte synchrone Beschreibung, die ich nicht verstehen kann.

Antworten (2)

Ich habe Ihren Code in eine vollständige synchrone Beschreibung umgearbeitet:

  1. Synchrone Designs brauchen ein Taktsignal, aber ein Tastensignal ist kein Takt. Jeder Prozess wird also bei einer positiven Flanke von ausgelöst Clk.
  2. Ich habe den Zustandstyp geändert, um einige Typkonvertierungen zu ersparen.
  3. Ist Aaktiv, dann wird der Zähler auf Null zurückgesetzt.
  4. Wenn andernfalls Baktiv ist, wird es inkrementiert.
  5. Ich nehme an, Ihr led_debugProzess sollte getaktet werden, also habe ich eine Rising_Edge-Bedingung hinzugefügt.

Diese Lösung löst das folgende Problem nicht, wenn Aund BDrähte von einer externen Taste sind:

  • Externe Signale müssen mit mindestens 2 FFs synchronisiert werden, um Metastabilitätsprobleme zu vermeiden.
  • Externe Taster benötigen meistens eine Entprellschaltung, da Tastereingänge prellen. Es sind auch elektrische oder mechanische Lösungen möglich, um das Problem zu lösen. Werfen Sie einen Blick in Ihre Board-Beschreibungen und Board-Schaltpläne.
  • In den meisten Fällen möchten Sie Tastendrücke zählen. Ihre aktuelle Lösung misst, wie lange Sie die Taste gedrückt haben (dies erfordert auch einen größeren Zähler). Dieses Problem kann durch eine Flankenerkennungsschaltung gelöst werden.

Hier ist der umgeschriebene Code:

entity simple is
  Port (
    CLK : in std_logic;
    A : in std_logic;
    B : in std_logic;
    debug : out std_logic_vector (7 downto 0)
  );
end entity;

architecture rtl of simple is
  signal state : unsigned(7 downto 0) := (others => '0');

begin
  increment : process(Clk)
  begin
    if rising_edge(Clk) then
      if (B = '1') then 
        state <= "00000000";
      elsif (A = '1') then 
        state <= state + 1;
      end if;
    end if;
  end process;

  led_debug : process(CLK)
  begin
    if rising_edge(Clk) then
      debug <= std_logic_vector(state);
    end if;
  end process;    
end architecture;
Das Hinzufügen eines weiteren Registers für debugist nicht unbedingt erforderlich.
Ich habe seinen Code übersetzt. Und ja, in einigen Fällen benötigen Sie 1 bis 3 Registerstufen für einen Debug-Port in einen internen Zustand. Die Debug-Schaltung ist natürlich mehr als eine LED ...

Mir wurde klar, dass es innerhalb desselben Prozesses an 2 steigenden Flanken überprüfte, wodurch das System empfindlich auf 2 Takte reagierte, was zu einer schlechten Synchronität führte.

Die B-Taste kann als asynchroner Reset verwendet werden.