Altera_Forum
Honored Contributor
12 years agoProblem with asynchronous FSM - VHDL
I have a problem with implementation of finite state machine, which is responsible for detection of motor direction based on signals from HALL sensors. The system has three inputs (HALL1, HALL2, HALL3) and one output (DIR - '1' for clockwise and '0' for counterclockwise direction). The problem is, that I don't have access to any external clock signal with I could synchronize the work of state machine and involve transitions of states. I tried to solve this problem in few ways, which finally failed:
I have tried to produce synchronization signal using HALL signals - I've just put them together to XOR gate, which gave me a square wave. I wanted to make a transition between states during falling, as also rising edge of the square signal, but I got an error message: "Error (10628): VHDL error at DIR_AUT_SL.vhd(87): can't implement register for two clock edges combined with a binary operator". Actually, I've done some research in this case and found information, that is impossible to make a signal sensitive on both (rising and falling edge). And here is my question - maybe is somebody on this forum, who had some similar problem and would like to give me an advice. Maybe I should implement an asynchronous state machine, which doesn't need a clock signal? But how can I make a transition between states in such a case? I would be very grateful for any help. My VHDL code is below:
library ieee ;
use ieee.std_logic_1164 .all;
use ieee.std_logic_signed .all;
entity DIR_AUT_SL is
port ( H1_SL, H2_SL, H3_SL, clock: in STD_LOGIC ;
DIR_SIGNAL_1 : out STD_LOGIC );
END DIR_AUT_SL;
architecture behavior of DIR_AUT_SL is
type state_type is (A, B, C, D, E, F, G, H, I, J, K, L);
signal y_act, y_next : state_type ;
signal hall: std_logic_vector (0 to 2);
begin
hall <= H1_SL&H2_SL&H3_SL;
process (hall, y_act) -- state table
begin
case y_act is
when A => case hall is
when "101" => y_next <= B;
when "110" => y_next <= L;
when others => y_next <= A;
end case;
when B => case hall is
when "001" => y_next <= C;
when "100" => y_next <= G;
when others => y_next <= B;
end case;
when C => case hall is
when "011" => y_next <= D;
when "101" => y_next <= H;
when others => y_next <= C;
end case;
when D => case hall is
when "010" => y_next <= E;
when "001" => y_next <= I;
when others => y_next <= D;
end case;
when E => case hall is
when "110" => y_next <= F;
when "011" => y_next <= J;
when others => y_next <= E;
end case;
when F => case hall is
when "100" => y_next <= A;
when "010" => y_next <= K;
when others => y_next <= F;
end case;
when G => case hall is
when "101" => y_next <= B;
when "110" => y_next <= L;
when others => y_next <= G;
end case;
when H => case hall is
when "001" => y_next <= C;
when "100" => y_next <= G;
when others => y_next <= H;
end case;
when I => case hall is
when "011" => y_next <= D;
when "101" => y_next <= H;
when others => y_next <= I;
end case;
when J => case hall is
when "010" => y_next <= E;
when "001" => y_next <= I;
when others => y_next <= J;
end case;
when K => case hall is
when "110" => y_next <= F;
when "011" => y_next <= J;
when others => y_next <= K;
end case;
when L => case hall is
when "100" => y_next <= A;
when "010" => y_next <= K;
when others => y_next <= L;
end case;
when others => y_act <= A;
end case ;
end process ; -- state_table
process (clock)
begin
if (rising_edge(clock) OR falling_edge (clock)) then
y_act <= y_next ;
end if;
end process ;
process ( y_act ) -- output states
begin
case y_act is
when A => DIR_SIGNAL_1 <= '1';
when B => DIR_SIGNAL_1 <= '1';
when C => DIR_SIGNAL_1 <= '1';
when D => DIR_SIGNAL_1 <= '1';
when E => DIR_SIGNAL_1 <= '1';
when F => DIR_SIGNAL_1 <= '1';
when G => DIR_SIGNAL_1 <= '0';
when H => DIR_SIGNAL_1 <= '0';
when I => DIR_SIGNAL_1 <= '0';
when J => DIR_SIGNAL_1 <= '0';
when K => DIR_SIGNAL_1 <= '0';
when L => DIR_SIGNAL_1 <= '0';
end case ;
end process ; -- output states
end behavior ;