VHDL状态机正在跳过状态
我正在用VHDL开发一个状态机,它似乎不能正常工作。设计如下所示:VHDL状态机正在跳过状态,vhdl,state-machine,Vhdl,State Machine,我正在用VHDL开发一个状态机,它似乎不能正常工作。设计如下所示: SHARED VARIABLE XM_INDEX : NATURAL RANGE 0 TO 99 := 0; SIGNAL XM_STATE_INDICATOR : STD_LOGIC_VECTOR (7 DOWNTO 0) := "00000000"; TYPE XM_STATE_TYPE IS (EMPTY, IDLE, POWER_UP, POWER_UP_CONFIRM,
SHARED VARIABLE XM_INDEX : NATURAL RANGE 0 TO 99 := 0;
SIGNAL XM_STATE_INDICATOR : STD_LOGIC_VECTOR (7 DOWNTO 0) := "00000000";
TYPE XM_STATE_TYPE IS (EMPTY, IDLE, POWER_UP, POWER_UP_CONFIRM,
CHANNEL_SELECT, CHANNEL_SELECT_CONFIRM, VOLUME_CHANGE,
VOLUME_CHANGE_CONFIRM, TRANSMIT_CHAR, TRANSMIT_CHAR_CONFIRM,
COMPLETED);
SIGNAL XM_CURRENT_STATE : XM_STATE_TYPE := EMPTY;
SIGNAL XM_NEXT_STATE : XM_STATE_TYPE := EMPTY;
XMStateMachineClock: PROCESS (CLK25, SYS_RST) IS
BEGIN
IF (SYS_RST = '1') THEN
XM_CURRENT_STATE <= EMPTY;
ELSIF (RISING_EDGE(CLK25)) THEN
XM_CURRENT_STATE <= XM_NEXT_STATE;
END IF;
END PROCESS XMStateMachineClock;
XMStateMachine: PROCESS (XM_CURRENT_STATE) IS
BEGIN
-- Pend on current XM state
CASE XM_CURRENT_STATE IS
-- Empty: Debug only
WHEN EMPTY =>
XM_NEXT_STATE <= IDLE;
XM_STATE_INDICATOR <= "00000001";
-- Idle: Idle state
WHEN IDLE =>
IF XM_POWER_UP = '1' THEN
XM_INDEX := 0;
XM_NEXT_STATE <= POWER_UP;
XM_STATE_INDICATOR <= "00000010";
ELSE
-- Remain in idle
XM_NEXT_STATE <= IDLE;
XM_STATE_INDICATOR <= "00000001";
END IF;
WHEN POWER_UP =>
XM_NEXT_STATE <= TRANSMIT_CHAR;
XM_STATE_INDICATOR <= "00000100";
WHEN TRANSMIT_CHAR =>
IF (XM_INDEX < 11) THEN
XM_NEXT_STATE <= TRANSMIT_CHAR_CONFIRM;
XM_STATE_INDICATOR <= "00001000";
ELSE
XM_NEXT_STATE <= COMPLETED;
XM_STATE_INDICATOR <= "00000000";
END IF;
WHEN TRANSMIT_CHAR_CONFIRM =>
XM_INDEX := XM_INDEX + 1;
XM_NEXT_STATE <= TRANSMIT_CHAR;
XM_STATE_INDICATOR <= "00000100";
WHEN COMPLETED =>
XM_NEXT_STATE <= COMPLETED;
XM_STATE_INDICATOR <= "00000000";
-- Default
WHEN OTHERS =>
END CASE;
END PROCESS XMStateMachine;
共享变量XM_索引:自然范围0到99:=0;
信号XM_状态_指示器:标准逻辑_向量(7到0):=“00000000”;
类型XM\u状态类型为(空、空闲、通电、通电确认、,
频道选择、频道选择确认、音量更改、,
音量更改确认,发送字符,发送字符确认,
已完成);
信号XM_当前状态:XM_状态类型:=空;
信号XM_NEXT_STATE:XM_STATE_TYPE:=空;
XMStateMachineLock:进程(CLK25,系统)为
开始
如果(SYS_RST='1'),则
XM_CURRENT_STATE如果您使XM_INDEX
信号有一个XM_INDEX_NEXT
锁存在xmstatemachinelock
过程中,然后将XM_INDEX:=XM_INDEX+1
更改为XM_INDEX_NEXT示例代码不存在竞争,并且有可能从共享变量更改XM_INDEX可能会打乱对于它的一些使用计划,应该有多个进程写入它。您可以注意到,用户负责控制-1993共享变量中的独占访问
通过提供完整的实体和体系结构对来创建:
library ieee;
use ieee.std_logic_1164.all;
entity xm_sm is
port (
clk25: in std_logic;
sys_rst: in std_logic;
xm_power_up: in std_logic
);
end entity;
architecture foo of xm_sm is
-- shared variable xm_index: natural range 0 to 99 := 0;
signal xm_index: natural range 0 to 99 := 0; -- CHANGED to SIGNAL
signal xm_index_nxt: natural range 0 to 99; -- ADDED
signal xm_state_indicator: std_logic_vector (7 downto 0) := "00000000";
type xm_state_type is (EMPTY, IDLE, POWER_UP, POWER_UP_CONFIRM,
CHANNEL_SELECT, CHANNEL_SELECT_CONFIRM,
VOLUME_CHANGE, VOLUME_CHANGE_CONFIRM,
TRANSMIT_CHAR, TRANSMIT_CHAR_CONFIRM,
COMPLETED);
signal xm_current_state: xm_state_type := EMPTY;
signal xm_next_state: xm_state_type := EMPTY;
begin
xmstatemachineclock:
process (clk25, sys_rst) is
begin
if sys_rst = '1' then
xm_current_state <= EMPTY;
xm_index <= 0; -- ADDED
elsif rising_edge(clk25) then
xm_current_state <= xm_next_state;
xm_index <= xm_index_nxt; -- ADDED
end if;
end process xmstatemachineclock;
xmstatemachine:
process (xm_current_state, xm_power_up) is
begin
-- pend on current xm state
case xm_current_state is
-- empty: debug only
when EMPTY =>
xm_next_state <= IDLE;
xm_state_indicator <= "00000001";
-- idle: idle state
when IDLE =>
if xm_power_up = '1' then
xm_index_nxt <= 0;
xm_next_state <= POWER_UP;
xm_state_indicator <= "00000010";
else
-- remain in idle
xm_next_state <= IDLE;
xm_state_indicator <= "00000001";
end if;
when POWER_UP =>
xm_next_state <= TRANSMIT_CHAR;
xm_state_indicator <= "00000100";
when TRANSMIT_CHAR =>
if xm_index < 11 then
xm_next_state <= TRANSMIT_CHAR_CONFIRM;
xm_state_indicator <= "00001000";
else
xm_next_state <= COMPLETED;
xm_state_indicator <= "00000000";
end if;
when TRANSMIT_CHAR_CONFIRM =>
if xm_index = 99 then -- protect again overflow -- ADDED
xm_index_nxt <= 0;
else
xm_index_nxt <= xm_index + 1; -- CHANGED
end if;
-- xm_index_nxt <= xm_index + 1;
xm_next_state <= TRANSMIT_CHAR;
xm_state_indicator <= "00000100";
when COMPLETED =>
xm_next_state <= COMPLETED;
xm_state_indicator <= "00000000";
-- default
when others =>
end case;
end process xmstatemachine;
end architecture;
其中,xm_循环由状态传输_CHAR_确认为锁存启用的一个热状态表示锁存
在模拟中,没有xm_索引的灵敏度列表将防止加法器波动增加xm_索引。如果xm_索引已经在进程敏感度列表中,那么在达到100之后,它将导致赋值的边界检查冲突。(整数类型不是模块化的,它们不包装,也不能防止溢出)
在没有看到控制台输出的合成中,我们可能会假设涟漪时间足以在一个时钟时间内可靠地将xm_索引的值推到11以上,而不会将其压缩到11以下。缺少一个解释。如果TRANSMIT_CHAR_CONFIRM可用作闩锁启用,则xm_index:=xm_index+1;当TRANSMIT\u CHAR\u CONFIRM为真时,将连续改变值存在一个组合循环。xm_索引成为一个门控振荡器,通过xm_索引的可能值波动。加法器延迟似乎在一个clk25中为您提供xm_索引>11。如果灵敏度列表中没有xm_索引,它甚至可以明显正确地模拟。合成工具通常会报告组合循环。您还可以使xm_索引成为时钟进程中分配的信号,如果xm_当前_状态=传输_字符_确认,则模拟xm_索引应防止溢出(或者将其设置为无符号数组类型值,并转换为未显示的其他用途-缺少MCVE的诅咒)。xm_power_up也应位于xmstatemachine进程的灵敏度列表中,以便进行模拟。您应将xmstatemachine
设置为时钟进程。
library ieee;
use ieee.std_logic_1164.all;
entity xm_sm_tb is
end entity;
architecture foo of xm_sm_tb is
signal clk25: std_logic := '0';
signal sys_rst: std_logic := '0';
signal xm_power_up: std_logic := '0';
begin
DUT:
entity work.xm_sm
port map (
clk25 => clk25,
sys_rst => sys_rst,
xm_power_up => xm_power_up
);
CLOCK:
process
begin
wait for 50 ns;
clk25 <= not clk25;
if now > 3.1 us then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 100 ns;
sys_rst <= '1';
wait for 100 ns;
sys_rst <= '0';
wait for 200 ns;
xm_power_up <= '1';
wait for 100 ns;
xm_power_up <= '0';
wait;
end process;
end architecture;
XM_INDEX := XM_INDEX + 1;