Altera_Forum
Honored Contributor
16 years agoFaulty State Machine
Hi there,
There is a bug in the following state machine that sometimes causes the state transits directly from standby to locked (or some undefined state and stays there) when the enable signal goes high, without going through detecting state. I think it's timing related bug, because for some compiles it seems to be working ok, but not quite sure on how to improve the code. Right now I am compiling a version that takes the n_pur out of the equation of the second process. Any suggestions? Appreciated. Hua
-- asd fsm sync process
process (n_pur, clk)
begin
if n_pur='0' then
asd_cs <= standby;
lock <= '0';
rate <= "00000";
rate_tmp1 <= "00000";
asd_pass_reg <= 0;
elsif rising_edge (clk) then
asd_cs <= asd_ns;
lock <= lock_tmp;
rate <= rate_tmp;
rate_tmp1 <= rate_tmp;
asd_pass_reg <= asd_pass;
end if;
end process;
-- asd fsm state transition
process (n_pur, asd_cs, enable, s2_rate, rate_tmp1, current_state, last_detected_rate, asd_pass_reg)
begin
if n_pur='0' then
lock_tmp <= '0';
state_tmp <= '0';
rate_tmp <= "00000";
counter_fsm_en <= '0';
asd_pass <= 0;
asd_ns <= standby;
else
case asd_cs is
when standby =>
lock_tmp <= '0';
state_tmp <= '0';
rate_tmp <= rate_tmp1;
counter_fsm_en <= '0';
asd_pass <= 0;
--last_detected_rate <="00000";
--if enable = '1' and current_state = standby then
if enable = '1' then
asd_ns <= detecting;
else
asd_ns <= standby;
end if;
when detecting =>
lock_tmp <= '0';
state_tmp <= '1';
--rate_tmp <= "00000";
rate_tmp <= rate_tmp1;
counter_fsm_en <= '1';
if s2_rate = last_detected_rate and s2_rate /= "00000" and output='1' then
asd_pass <= asd_pass_reg+1;
else
asd_pass <= 0;
end if;
if enable = '0' then
asd_ns <= standby;
elsif asd_pass >= asd_max_pass-1 then
asd_ns <= locked;
else
asd_ns <= detecting;
end if;
when locked =>
lock_tmp <= '1';
state_tmp <= '0';
rate_tmp <= s2_rate;
counter_fsm_en <= '0';
asd_pass <= 0;
if enable = '0' then
asd_ns <= standby;
else
asd_ns <= locked;
end if;
when others =>
lock_tmp <= lock_tmp;
state_tmp <= '0';
rate_tmp <= rate_tmp1;
counter_fsm_en <= '0';
asd_pass <= 0;
asd_ns <= standby;
end case;
end if;
end process;