状态改变后返回初始状态的问题

时间:2018-03-06 10:02:22

标签: vhdl fsm

我刚刚开始使用VHDL,似乎在我从状态NTIME进行初始更改到SET_TIME后,我无法返回{{1} }以便能够更改回NTIME

我已经检查了SET_ALARM - 块之前的信号,它似乎已正确创建并收到。但我似乎只是陷入case。当收到带有编码SET_TIME的按钮时,会发生从NTIMESET_TIME的更改。当第二次接收到该信号时,该状态应该返回到原始状态'0001'。状态NTIME的输入'0010'也会出现类似的情况。

这是我到目前为止所做的:

SET_ALARM

我不确定这只是对VHDL的基本误解,也可能只是一个错字。

这是我的测试台:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity controller is
  port(
    btn : in  std_logic_vector(3 downto 0);
    sw : in  std_logic_vector(0 downto 0);
    o_mins, o_secs, o_wmins : out integer range 0 to 59;
    o_hours, o_whours : out integer range 0 to 23;
    alarm : out std_logic;
    state : out std_logic_vector(1 downto 0);
    clk : in  std_logic;
    reset : in  std_logic
  );
end controller;

architecture Behavioral of controller is

  component trigger_gen is
    generic(Delta : integer);
    port(
      clk   : in std_logic;
      reset : in std_logic;
      trigger : out std_logic
    );
  end component trigger_gen;

  -- pro Viertelsekunde einen Takt lang '1'
  signal fasttrigger : std_logic;
  -- fasttrigger wird zurueckgesetzt, wenn BTN2 oder BTN3 gedrueckt werden
  signal fasttimer_reset : std_logic;
  -- pro Sekunde einen Takt lang '1'
  signal sectrigger : std_logic;

  signal hours, whours     : integer range 0 to 23;
  signal secs, mins, wmins : integer range 0 to 59;

  -- fuer Flankenerkennung der Taster
  signal btn_shift : std_logic_vector(3 downto 0);
  signal btn_triggered : std_logic_vector(3 downto 0);

  type state_type is (NTIME, SET_TIME, SET_ALARM, error);
  signal current_state : state_type;

begin
  fasttimer_reset <= reset or
        btn_triggered(2) or btn_triggered(3);

  fasttimer : trigger_gen
    generic map(11)
    port map(clk, fasttimer_reset, fasttrigger);

  sectimer : trigger_gen
    generic map(13)
    port map(clk, reset, sectrigger);

  FSM : process(clk, reset)
    variable next_state : state_type;
  begin
    if reset = '1' then
      hours  <= 0;
      mins   <= 0;
      secs   <= 0;
      whours <= 0;
      wmins  <= 0;
      alarm  <= '0';
      current_state <= NTIME;
    elsif clk'event and clk = '1' then
      for i in 0 to 3 loop
        btn_shift(i) <= btn(i);
        btn_triggered(i) <= not btn_shift(i) and btn(i);
      end loop;

        -- TODO: Zaehle Uhr hoch
        IF secs <= 58 THEN 
            secs <= secs + 1;
        ELSE
            secs <= 0;
            IF mins <= 58 THEN
                mins <= mins + 1;
            ELSE
                mins <= 0;
                IF hours <= 22 THEN
                    hours <= hours + 1; 
                ELSE
                    hours <= 0;
                END IF;
            END IF;
        END IF;




      -- TODO: Pruefe, ob Alarm ausgeloest werden muss
      IF hours = whours AND mins = wmins AND sw(0) = '1' THEN
        alarm <= '1';
      END IF;
      case current_state is
        -- Zustand Time
        when NTIME =>
            IF btn_triggered(0) = '1'  THEN
              REPORT "Going to set time";
              next_state := SET_TIME;
            ELSIF btn_triggered(1) = '1' THEN
            REPORT "Going to set Alarm";
              next_state := SET_ALARM;
            END IF;

        -- Zustand SetTime
        when SET_TIME =>
            IF btn_triggered(0) = '1' THEN
                next_state := NTIME;
            END IF;

            IF  btn_triggered(2) = '1' THEN
                REPORT "SETTING MINUTES IN TIME";
                IF mins <= 58 THEN
                    mins <= mins + 1;
                ELSE
                    mins <= 0;
                END IF;
            ELSIF btn_triggered(3) = '1' THEN
                REPORT "SETTING HOURS IN TIME";
                IF hours <= 22 THEN
                    hours <= hours + 1;
                ELSE
                    hours <= 0;
                END IF;
            END IF;

        -- Zustand SetAlarm
        when SET_ALARM =>
            IF btn_triggered(1) = '1' THEN
                next_state := NTIME;
            END IF;
            IF btn_triggered(2) = '1' THEN
                REPORT "SETTING MINUTES IN ALARM";
                IF wmins <= 58 THEN
                    wmins <= wmins + 1;
                ELSE
                    wmins <= 0;
                END IF;
            ELSIF btn_triggered(3) = '1' THEN
                REPORT "SETTING HOURS IN ALARM";
                IF whours <= 22 THEN
                    whours <= whours + 1;
                ELSE
                    whours <= 0;
                END IF;
            END IF;

            next_state := NTIME;

          -- Illegale Zustaende
        when others =>
          next_state := NTIME;
      end case;

      current_state <= next_state;
    end if;
  end process FSM;

  o_hours  <= hours;
  o_mins   <= mins;
  o_secs   <= secs;
  o_whours <= whours;
  o_wmins  <= wmins;

  with current_state select
    state <= "00" when NTIME,
             "01" when SET_TIME,
             "10" when SET_ALARM,
             "11" when others;
end architecture Behavioral;

0 个答案:

没有答案