Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VHDL状态机正在跳过状态_Vhdl_State Machine - Fatal编程技术网

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,

我正在用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, 
                       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;