簡體   English   中英

如何在不接受來自 Basysy3 FPGA 的多個輸入的情況下將有限狀態機正確實現到 VHDL 中

[英]How do I correctly implement a Finite-State Machine into VHDL without taking in multiple inputs from Basysy3 FPGA

我是 VHDL 的新手,我正在嘗試將以下狀態機實現到 VHDL(下面提供的狀態圖)中。 當我按下 Basys3 FPGA 板上的按鈕(P 輸入)時,輸出是隨機狀態。 我懷疑這是因為時鍾在單次按下期間經歷了許多周期,因此從單次按下時接收了 1 個以上的輸入,但我不確定。 有什么我可以做的來解決這個問題。 我希望能夠按下按鈕 P 並且狀態一次改變一個。

在此處輸入圖片說明


library IEEE;
USE ieee.std_logic_1164.all;

ENTITY trasher is
PORT (
      clock :   IN STD_LOGIC;
      P     :   IN STD_LOGIC;
      reset :   IN STD_LOGIC;
      LED3, LED1,LED2,LED0     :    OUT STD_LOGIC);
END ENTITY;

-- Architecture definition for the SimpleFSM entity
Architecture RTL of trasher is
TYPE State_type IS (A, B, C, D);  -- Define the states
    SIGNAL State : State_Type;    -- Create a signal that uses 
                                  -- the different states

BEGIN 
  PROCESS (clock, reset) 
  BEGIN 
    IF (reset = '1') THEN            -- upon reset, set the state to A
        State <= A;
 
    ELSIF rising_edge(clock) THEN    -- if there is a rising edge of the
                             -- clock, then do the stuff below
 
        -- The CASE statement checks the value of the State variable,
        -- and based on the value and any other control signals, changes
        -- to a new state.
        CASE State IS
            -- If the current state is A and P is set to 1, then the
            -- next state is B
            WHEN A => 
                IF P='1' THEN 
                    State <= B; 
                END IF; 
            -- If the current state is B and P is set to 1, then the
            -- next state is C
            WHEN B => 
                IF P='1' THEN 
                    State <= C; 
                END IF; 
            -- If the current state is C and P is set to 1, then the
            -- next state is D
            WHEN C => 
                IF P='1' THEN 
                    State <= D; 
                END IF; 
            -- If the current state is D and P is set to 1, then the
            -- next state is B.
            -- If the current state is D and P is set to 0, then the
            -- next state is A.
            WHEN D=> 
                IF P='1' THEN 
                    State <= B; 
                ELSE 
                    State <= A; 
                END IF; 
            WHEN others =>
                State <= A;
        END CASE; 
    END IF; 
  END PROCESS;
  
  -- Decode the current state to create the output
  -- if the current state is D, R is 1 otherwise R is 0

  LED0 <= '1' WHEN State=A ELSE '0';
  LED1 <= '1' WHEN State=B ELSE '0';
  LED2 <= '1' WHEN State=C ELSE '0';
  LED3 <= '1' WHEN State=D ELSE '0';
END rtl;

不要直接使用來自按鈕的輸入。 您需要饋送狀態機的是P的上升沿檢測器的輸出,而不是P本身。

此外, P與您的主時鍾不同步,因此存在亞穩態風險。 最后但並非最不重要的是,如果它反彈,您將獲得多個值更改,而不僅僅是一個。 為了解決亞穩定性問題,您需要一個重新同步器,它只是一個移位寄存器。 您還可以使用它來生成一個中間信號,該信號僅在按下按鈕時的一個時鍾周期內被斷言為高電平,即狀態機所需的上升沿檢測器。 3 階段示例:

signal sync: std_ulogic_vector(0 to 2);
signal button_pressed: std_ulogic;
...
process(clock, reset)
begin
  if reset = '1' then
    sync <= (others => '0');
  elsif rising_edge(clock) then
    sync <= P & sync(0 to 1);
  end if;
end process;
    
button_pressed <= sync(1) and (not sync(2));

sync第 1 階段和第 2 階段可以安全使用,因為它們已經重新同步(假設 2 個階段足以滿足您的目標技術和平均故障間隔時間;如果您不了解這一點,請閱讀有關元穩定性的內容)。

當按下按鈕時,它們會sync移動。 在兩個時鍾周期后, sync = "110"所以button_pressed被置為高電平。 一個時鍾周期后, sync = "111"並且button_pressed被取消斷言。 因此, button_pressed是一個只有一個時鍾周期的指示器,表明按鈕被按下。 您可以將其用作狀態機的輸入。

第二個問題來自按鈕的工作方式。 如果您的原型板還沒有消除其按鈕的抖動,那么當按下按鈕時,您的P輸入會在 0 和 1 之間振盪數次,然后穩定為 1。釋放按鈕時也是如此。 由於有時情況並非如此,因此在實施去抖器之前進行一些測試。 例如,計算button_pressed被置為高電平的次數並將其發送到您的 LED:

signal cnt: u_unsigned(3 downto 0);
...
process(clock, reset)
begin
  if reset = '1' then
    cnt <= (others => '0');
  elsif rising_edge(clock) then
    cnt <= cnt + button_pressed;
  end if;
end process;

LED0 <= std_logic(cnt(0));
LED1 <= std_logic(cnt(1));
LED2 <= std_logic(cnt(2));
LED3 <= std_logic(cnt(3));

如果您的按鈕彈跳,您有時應該看到的不僅僅是增量。 是時候搜索一些關於去抖動的信息,並在需要時提出一個新問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM