シリアル入力に基づいて状態を切り替える有限状態マシンを作成しようとしています。コードの実行方法について説明が必要です。教科書で、「DEFAULT VALUES」とマークしたプロセスのセクションにデフォルト値を配置する必要があることを読みました。ただし、状態を切り替えるたびに、信号はこれらの値をとるようです。たとえば、state_next をデフォルト値の idle に設定します。これを行うと、FSM が理由もなく他の状態からアイドル状態にジャンプし続けます。
もう 1 つの質問は、FSM のプロセス全体がどのように実行されるかを明確にすることです。ある状態から別の状態に移行する場合、case ステートメントの前のセクション (DEFAULT VALUES とマークされた部分) が実行されることになっていますか? それとも、後の状態からアイドル状態に戻った場合にのみ実行されますか? DEFAULT VALUES セクションはいつ実行されることになっていますか?
私のコードを以下に示します。「次の状態のロジック」セクションを参照してください。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity delay_incrementor is
generic ( delay_ports : natural := 3;
width_ports : natural := 3
);
Port ( clk,reset: in STD_LOGIC;
update : in STD_LOGIC;
in_data : in STD_LOGIC_VECTOR (7 downto 0);
led : out STD_LOGIC_VECTOR (2 downto 0);
out_data : out STD_LOGIC_VECTOR (7 downto 0);
d_big,d_mini,d_opo : inout STD_LOGIC_VECTOR (25 downto 0);
w_big,w_mini,w_opo : inout STD_LOGIC_VECTOR (25 downto 0));
end delay_incrementor;
architecture fsm_arch of delay_incrementor is
type state_type is (idle,channel,d_or_w,delay_channel,delay_channel_inc,width_channel,width_channel_inc);
type delay_file_type is array (delay_ports-1 downto 0) of std_logic_vector (25 downto 0);
type width_file_type is array(width_ports-1 downto 0) of std_logic_vector (25 downto 0);
signal d_reg,d_next,d_succ: delay_file_type;
signal w_reg,w_next,w_succ: width_file_type;
signal state_reg,state_next: state_type;
signal which_channel,which_channel_next: natural;
begin
--------------------------------------
--State Register
--------------------------------------
process(clk,reset)
begin
if reset='1' then
state_reg <= idle;
d_reg <= (others => (others => '0'));
w_reg <= (others => (others => '0'));
which_channel <= 0;
elsif (clk='1' and clk'event) then
state_reg <= state_next;
d_reg <= d_next;
w_reg <= w_next;
which_channel <= which_channel_next;
end if;
end process;
--------------------------------------
--Next-State Logic/Output Logic
--------------------------------------
process(state_reg,in_data,d_reg,w_reg,which_channel)
begin
state_next <= idle; --DEFAULT VALUES
d_succ <= d_reg;
w_succ <= w_reg;
which_channel_next <= 0;
case state_reg is
when idle =>
if in_data = "01100011" then --"c"
state_next <= channel;
which_channel_next <= 0;
end if;
when channel =>
if (48 <= unsigned(in_data)) and (unsigned(in_data)<= 57) then
which_channel_next <= (to_integer(unsigned(in_data))-48);
state_next <= d_or_w;
elsif in_data = "00100011" then --"#"
state_next <= idle;
which_channel_next <= which_channel;
end if;
when d_or_w =>
if in_data = "01100100" then --"d"
state_next <= delay_channel;
elsif in_data = "01110111" then --"w"
state_next <= width_channel;
elsif in_data = "00100011" then --"#"
state_next <= idle;
end if;
when delay_channel =>
if in_data = "01101001" then --"i"
state_next <= delay_channel_inc;
elsif in_data = "00100011" then --"#"
state_next <= idle;
end if;
when delay_channel_inc =>
if in_data = "01110101" then --"u"
d_succ(which_channel) <= std_logic_vector(unsigned(d_reg(which_channel))+250);
elsif in_data = "01100100" then --"d"
d_succ(which_channel) <= std_logic_vector(unsigned(d_reg(which_channel))-250);
else
d_succ(which_channel) <= d_reg(which_channel);
end if;
if in_data = "00100011" then --"#"
state_next <= idle;
end if;
when width_channel =>
if in_data = "01101001" then --"i"
state_next <= width_channel_inc;
elsif in_data = "00100011" then --"#"
state_next <= idle;
end if;
when width_channel_inc =>
if in_data = "01110101" then --"u"
w_succ(which_channel) <= std_logic_vector(unsigned(w_reg(which_channel))+250);
elsif in_data = "01100100" then --"d"
w_succ(which_channel) <= std_logic_vector(unsigned(w_reg(which_channel))-250);
else
w_succ(which_channel) <= w_reg(which_channel);
end if;
if in_data = "00100011" then --"#"
state_next <= idle;
end if;
end case;
end process;
process(update,d_reg,w_reg,reset)
begin
if reset='1' then
d_next <= (others => (others =>'0'));
w_next <= (others => (others =>'0'));
elsif (update'event and update='1') then
d_next <= d_succ;
w_next <= w_succ;
else
d_next <= d_reg;
w_next <= w_reg;
end if;
end process;
--------------------------------------
--Output Logic
--------------------------------------
d_big <= d_reg(0);
d_mini <= d_reg(1);
d_opo <= d_reg(2);
w_big <= w_reg(0);
w_mini <= w_reg(1);
w_opo <= w_reg(2);
end fsm_arch;