0

Lattice XP2-5E チップを搭載した FPGA ボードをプログラミングしています。ボード上には、4 つの方向プッシュ ボタンと 1 つのリセット プッシュ ボタンで制御しようとしている 4 行 2 列の LED ライトもあります。たとえば、(1 行目/1 列目) LED がオンの場合、ボタンを右に押すと、(1 行目/2 列目) LED がオンになり、(1 行目/1 列目) LED がオフになります。

組み込みのハードウェア デバウンス回路が実装されていないため、VHDL ソリューションを実装する必要があります。ティック レートは 25 MHz で、最小ボタン ホールド時間は 25 ミリ秒です。コードを以下に示します。

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