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 ミリ秒よりはるかに長い時間)。
問題に見えるのは。アイデアが不足しています。