0

我正在使用 Lattice XP2-5E 芯片对 FPGA 板进行编程。板上还有 4 行 2 列 LED 灯,我试图用 4 个方向按钮和一个复位按钮来控制它们。例如,如果(第 1 行/第 1 列)LED 亮起,如果我按下右按钮,(第 1 行/第 2 列)LED 将亮起,(第 1 行/第 1 列)LED 将熄灭。

由于没有实现内置的硬件去抖动电路,我需要实现一个 VHDL 解决方案。滴答频率为 25 MHz,最小按钮保持时间为 25 ms。代码如下所示:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity SKLOP is
port (  btn_center : in std_logic;
        btn_left : in std_logic;
        btn_right : in std_logic;
        btn_up : in std_logic;
        btn_down : in std_logic;

        clk_25m : in std_logic;

        led : out std_logic_vector (7 downto 0));
end SKLOP;

architecture behv of SKLOP is

    type state_type is (s0, s1, s2, s3, s4, s5, s6, s7);
    signal CurS : state_type := s0;
    signal NxtS : state_type := s0;
    signal counter : std_logic_vector (22 downto 0) := (others => '0');
    signal is_ok : std_logic := '0';
    signal btn_press : std_logic := '0';
    signal start_cnt : std_logic := '0';

begin

    process(is_ok)                                -- state switching
    begin

        if(btn_left = '1' and rising_edge(is_ok)) then
            case CurS is
                when s0 =>
                    NxtS <= s0;
                when s1 =>
                    NxtS <= s1;
                when s2 =>
                    NxtS <= s2;
                when s3 =>
                    NxtS <= s3;
                when s4 =>
                    NxtS <= s0;
                when s5 =>
                    NxtS <= s1;
                when s6 =>
                    NxtS <= s2;
                when s7 =>
                    NxtS <= s3;
            end case;
        end if;

        if(btn_right = '1' and rising_edge(is_ok)) then
            case CurS is
                when s0 =>
                    NxtS <= s4;
                when s1 =>
                    NxtS <= s5;
                when s2 =>
                    NxtS <= s6;
                when s3 =>
                    NxtS <= s7;
                when s4 =>
                    NxtS <= s4;
                when s5 =>
                    NxtS <= s5;
                when s6 =>
                    NxtS <= s6;
                when s7 =>
                    NxtS <= s7;
            end case;
        end if;

        if(btn_up = '1' and rising_edge(is_ok)) then
            case CurS is
                when s0 =>
                    NxtS <= s0;
                when s1 =>
                    NxtS <= s0;
                when s2 =>
                    NxtS <= s1;
                when s3 =>
                    NxtS <= s2;
                when s4 =>
                    NxtS <= s4;
                when s5 =>
                    NxtS <= s4;
                when s6 =>
                    NxtS <= s5;
                when s7 =>
                    NxtS <= s6;
            end case;
        end if;

        if(btn_down = '1' and rising_edge(is_ok)) then
            case CurS is
                when s0 =>
                    NxtS <= s1;
                when s1 =>
                    NxtS <= s2;
                when s2 =>
                    NxtS <= s3;
                when s3 =>
                    NxtS <= s3;
                when s4 =>
                    NxtS <= s5;
                when s5 =>
                    NxtS <= s6;
                when s6 =>
                    NxtS <= s7;
                when s7 =>
                    NxtS <= s7;
            end case;
        end if;

        if(btn_center = '1' and rising_edge(is_ok)) then
            NxtS <= s0;
        end if;

    end process;

    process(CurS)                                   -- output of state machine
    begin
        case CurS is
            when s0 =>
                led <= "10000000";
            when s1 =>
                led <= "01000000";
            when s2 =>
                led <= "00100000";
            when s3 =>
                led <= "00010000";
            when s4 =>
                led <= "00001000";
            when s5 =>
                led <= "00000100";
            when s6 =>
                led <= "00000010";
            when s7 =>
                led <= "00000001";
        end case;
    end process;

    process(clk_25m)                                -- debouncing
    begin
        if(btn_center = '1' or btn_right = '1' or btn_left = '1' or btn_up = '1' or btn_down = '1') then
            btn_press <= '1';
        else
            btn_press <= '0';
        end if;

        if(rising_edge(btn_press)) then
            start_cnt <= '1';
        end if;
        if(falling_edge(btn_press)) then
            start_cnt <= '1';
        end if;

        if(rising_edge(clk_25m)) then
            if(counter /= "10111110101111000010000" and start_cnt = '1') then
                counter <= counter + '1';
                is_ok <= '0';
            elsif(start_cnt = '1' and btn_press = '1') then
                is_ok <= '1';
                CurS <= NxtS;
                start_cnt <= '0';
                counter <= "00000000000000000000000";
            end if;
        end if;

    end process;

end behv;

有时代码会按预期工作,但通常会打开多个 LED 灯或没有打开 LED - 我想知道这怎么可能 - 有时按下按钮时状态不会改变(即使按住按钮超过 25 毫秒)。

似乎是什么问题。我的想法不多了。

4

0 回答 0