简体   繁体   English

如何在不接受来自 Basysy3 FPGA 的多个输入的情况下将有限状态机正确实现到 VHDL 中

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

I am new to VHDL and I am attempting to implement the following state machine into VHDL (state diagram provided below).我是 VHDL 的新手,我正在尝试将以下状态机实现到 VHDL(下面提供的状态图)中。 When I press a button on my Basys3 FPGA board( P input) the output is a random state.当我按下 Basys3 FPGA 板上的按钮(P 输入)时,输出是随机状态。 I suspect this is because the clock is going through many cycles during a single press so more than 1 input is being taken in from a single press but I am unsure.我怀疑这是因为时钟在单次按下期间经历了许多周期,因此从单次按下时接收了 1 个以上的输入,但我不确定。 Is there anything I can do to fix this.有什么我可以做的来解决这个问题。 I want to be able to press button P and the states change one at a time.我希望能够按下按钮 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;

Do not use directly the input from your press-button.不要直接使用来自按钮的输入。 What you need to feed your state machine is the output of a rising edge detector of P , not P itself.您需要馈送状态机的是P的上升沿检测器的输出,而不是P本身。

Moreover P is not synchronous with your master clock and there is thus a risk of meta-stability.此外, P与您的主时钟不同步,因此存在亚稳态风险。 Last but not least, if it bounces, you will get several value changes instead of just one.最后但并非最不重要的是,如果它反弹,您将获得多个值更改,而不仅仅是一个。 To solve the meta-stability issue you need a re-synchronizer, which is just a shift register.为了解决亚稳定性问题,您需要一个重新同步器,它只是一个移位寄存器。 And you can also use it to generate an intermediate signal that is asserted high during only one clock period when the button is pressed, that is, the rising edge detector you need for your state machine.您还可以使用它来生成一个中间信号,该信号仅在按下按钮时的一个时钟周期内被断言为高电平,即状态机所需的上升沿检测器。 Example with 3-stages: 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));

Stages 1 and 2 of sync are safe to use because they have already been resynchronized (assuming 2 stages are enough for your target technology and mean time between failures; read something about meta-stability, maybe, if you don't understand this). sync第 1 阶段和第 2 阶段可以安全使用,因为它们已经重新同步(假设 2 个阶段足以满足您的目标技术和平均故障间隔时间;如果您不了解这一点,请阅读有关元稳定性的内容)。

When the button is pressed, ones are shifted in sync .当按下按钮时,它们会sync移动。 After two clock periods sync = "110" so button_pressed is asserted high.在两个时钟周期后, sync = "110"所以button_pressed被置为高电平。 One clock period later sync = "111" and button_pressed is de-asserted.一个时钟周期后, sync = "111"并且button_pressed被取消断言。 button_pressed is thus a one-clock-period-only indicator that the button was pressed.因此, button_pressed是一个只有一个时钟周期的指示器,表明按钮被按下。 You can use it as an input of your state machine.您可以将其用作状态机的输入。

The second problem comes from the way press-buttons work.第二个问题来自按钮的工作方式。 If your prototyping board does not already debounce its press-buttons it can be that, when the button is pressed, your P input oscillates several times between 0 and 1 before stabilizing to 1. Same when the button is released.如果您的原型板还没有消除其按钮的抖动,那么当按下按钮时,您的P输入会在 0 和 1 之间振荡数次,然后稳定为 1。释放按钮时也是如此。 As this is sometimes not the case do some tests before implementing a debouncer.由于有时情况并非如此,因此在实施去抖器之前进行一些测试。 For instance, count the number of times button_pressed is asserted high and send this to your LEDs:例如,计算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));

If your button bounces you should sometimes see more than on increment.如果您的按钮弹跳,您有时应该看到的不仅仅是增量。 It will be time to search a bit about debouncing and, if needed, to ask a new question.是时候搜索一些关于去抖动的信息,并在需要时提出一个新问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM