Considere el siguiente diagrama de estado donde las entradas son c
y v
. El sistema también recibe un reloj de alta frecuencia clk
, aproximadamente 50 MHz.
Comosemuestraeneldiagrama,laprimeraentradaseusaparaavanzaraladerechaenlosestadosylasegundaentradaesparaavanzaralaizquierdaenlosestados.Enlaimplementacióndehardware(AlteraDE1)estasentradassonbotones.
Elproblemaesque,comolafrecuenciadelrelojesmuyalta(enrelaciónconladuracióndelapulsacióndelbotón),cuandosepresionaelbotónc
,caehastaelúltimoestadoS3
.Luego,sisepresionaelbotónv
,nuevamentepasaporelestadoinicialS0
.LosestadosintermediosS1
yS2
solosevisitanbrevemente.Lasiguientefigurailustralasituación.
Aquí está el código de mi VHDL para implementar la máquina de estado.
Primer código. Funciona pero el estado fracasa.
Library IEEE;
Use IEEE.std_logic_1164.all;
Entity state_machine is
port (
clk, c, v : in std_logic;
outp : out std_logic_vector(1 downto 0)
);
end state_machine;
Architecture beh of state_machine is
type state_type is (S0, S1, S2, S3); -- there are four states
signal current_state : state_type := S0 ;
Begin
Process(clk)
Begin
if (clk'event and clk = '1' ) then
case current_state is
when S0 =>
if c = '1' then
current_state <= S1;
end if;
when S1 =>
if c = '1' then
current_state <= S2;
elsif v = '1' then
current_state <= S0;
end if;
when S2 =>
if c = '1' then
current_state <= S3;
elsif v = '1' then
current_state <= S1;
end if;
when S3 =>
if v = '1' then
current_state <= S2;
end if;
End case;
End if;
End Process;
With current_state select
outp <= "00" when S0,
"01" when S1,
"10" when S2,
"11" when S3;
End beh;
En un experimento, reduje el reloj hacia abajo a 2 Hz. Funciona como se pretende en el diagrama de estado anterior, pero no es muy confiable. A veces avanza un estado, a veces "pierde" el reloj, a veces avanza dos estados. Seguramente esto no es aceptable.
También intenté separar el reloj y la lógica de la máquina de estado, en el siguiente código.
Segundo código. Se compila, pero la salida no está definida.
Library IEEE;
Use IEEE.std_logic_1164.all;
Entity state_machine_2 is
port (
clk, c, v : in std_logic;
outp : out std_logic_vector(1 downto 0)
);
end state_machine_2;
Architecture beh of state_machine_2 is
type state_type is (S0, S1, S2, S3); -- there are four states
signal current_state : state_type := S0 ;
signal next_state : state_type := S0 ;
Begin
Process(clk)
Begin
if (clk'event and clk = '1' ) then
current_state <= next_state ;
end if;
End Process;
Process(c, v)
Begin
Case current_state is
when S0 =>
if c = '1' then
next_state <= S1;
end if;
when S1 =>
if c = '1' then
next_state <= S2;
elsif v = '1' then
next_state <= S0;
end if;
when S2 =>
if c = '1' then
next_state <= S3;
elsif v = '1' then
next_state <= S1;
end if;
when S3 =>
if v = '1' then
next_state <= S2;
end if;
End case;
End Process;
With current_state select
outp <= "00" when S0,
"01" when S1,
"10" when S2,
"11" when S3;
End beh;
El código anterior se compila, pero la salida resultante no está definida.
Mi pregunta.
¿Cómo implementar el diagrama de estado anterior en VHDL y funcionaría como uno esperaría? Es decir, uno presiona c
una vez y simplemente avanzaría un estado solamente.
¿Quizás no debería estar usando el reloj en el FSM por completo? ¿O hay una mejor estrategia?