Regreso del estado inactivo

Tengo 5 estados: inactivo, estado1, estado2, estado3, estado4. A veces necesito ir a inactivo de acuerdo con mi diseño, y cuando vuelvo de inactivo, no quiero comenzar desde el principio, quiero comenzar desde el último estado en el que estaba. Pensé en hacer esto en inactivo como

if (statereg = 2) then
my_state <= state2;
end if;

¿Es este un buen enfoque o no funcionará? ¿Hay mejores formas? ¿Cómo manejan los gurús de VHDL este tipo de situaciones? ¿Cómo llamamos a este método en VHDL? ¿Tiene un nombre?

Proporcione más información sobre lo que está tratando de lograr con el código y/o el código de máquina de estado completo que implementó.
La terminología UML para lo que está describiendo es "transición al estado histórico". Aquí hay un ejemplo del pseudoestado de UML History .

Respuestas (3)

¿Qué tan complicado es su estado "inactivo"?

Si es relativamente simple, tal vez sería mejor simplemente replicarlo; en otras palabras, tener estados idle1, idle2, etc. separados, uno para cada uno de los estados activos.

La pregunta no está clara, pero suponiendo que desea que todos los demás estados que no sean inactivos sean persistentes e inactivos para volver a cualquier estado persistente, el siguiente enfoque lo logrará sin agregar muchos estados adicionales ...

type state_type is (idle, state1, state2, state3, state4);
signal state, saved_state : state_type;
signal reset, leave_idle, suspend, proceed : boolean;
procedure start_calculation;

process(clock)
begin
   if rising_edge(clock) then
      if reset then
         state       <= idle;
         saved_state <= state1;
      else
         -- default assignments : save current state
         saved_state <= state;

         -- main state machine
         case state is

         when idle =>
            -- override default assignment here; last assignment wins
            saved_state <= saved_state;
            if leave_idle then
               state <= saved_state;
            end if;

         when state1 =>
            if suspend then
               state <= idle;
            elsif proceed then
               start_calculation;
               state <= state2;
            -- else remain here
            end if;

         -- when state2 => 
         -- etcetera

         when others =>
            state <= idle;
         end case;
      end if;
   end if;
end process;
Paso por los estados: 1,2,3,4 secuencialmente cuando ocurre un caso inactivo. No quiero comenzar a escanear desde el principio, sino desde donde lo dejé.
Si entiendo correctamente su implementación, saved_statese stateretrasa 1 cc, por lo que si permanece en un estado por más de 1 cc, entonces el guardado y el actual son los mismos.
@Stacey: sí (excepto, por supuesto, para el estado inactivo), la idea es que siempre regrese después de Idle al estado que lo "llamó", tratando Idle como una subrutina. Puede que eso no sea lo que realmente quería el cartel, lo que todavía no está claro para mí.
@Brian, ¿entonces tu intención es vivir solo en inactivo por 1cc? Además, ¿estás mucho en el chat? Me encantaría hablar con alguien que tenga más experiencia en hdl que yo. Es una de las desventajas de ser freelance.
¿Qué hace si "leave_idle" es falso? ... Nunca he probado el chat, pero lo intentaré...

Guardaría el estado anterior al mismo tiempo que guarda su estado actual. Por ejemplo, defina dos señales del mismo tipo de máquina de estado:

 type states is (idle, state1, ... other states);

  signal current_state  : state;
  signal previous_state : state;

En su máquina de estado, cada vez que current_statecambia a un estado diferente, previous_stateestablezca current_state.

Esto hace que previous statesiempre esté un paso atrás current state.

Luego, en su estado inicial, simplemente configure current_statecuándo previous_statedesea volver a donde estaba.

  example_state_machine : process (clk, rst)
  begin 
    if rst = '1' then
      current_state  <= idle;
      previous_state <= state1; -- set this to the state you want to go to after first idle
    elsif clk'event and clk = '1' then  -- rising clock edge
      case current is
        when idle =>
          if (something = '1') then
            current_state  <= previous_state;
            previous_state <= current_state;
          else
            current_state <= idle;
          end if;
        when state1 =>
          if (something = '1') then
            current_state  <= state2;
            previous_state <= current_state;
          elsif something_else = '1' then
            current_state  <= idle;
            previous_state <= current_state;
          else
            current_state <= state1;
          end if;
          -- ... rest of states
        when others => null;
      end case;
    end if;
  end process;
¿Cómo sale esto de inactivo después del reinicio?
Dejando a un lado el comentario sarcástico, la idea básica es sólida.
@BrianDrummond, eh, buen punto. Cambiado previous_statea state1durante el reinicio.