Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21592 Discussions

Simple State Machine not working as expected

Altera_Forum
Honored Contributor II
2,044 Views

Hi, guys! 

So, I'm new here. I'm a student whose lab professor gave him the following assignment. Translated from spanish to english, it reads like this: 

An electrical engine is controlled by a single button. When the button is pushed, the engine is turned on. When the button is pushed again, the engine returns to 'off' status. Syntethize the engine's control circuit in VHDL.And then I have to program a FPGA with it, SignalTap it, and show the professor that it works as intended. The FPGA I'm using is a Cyclone III EP3C16F484C6. 

Since the pushable button I use continuously sends a '1' signal when it's not pushed, and a '0' signal while it's pushed, I wrote the following VHDL code for the assignment. 

 

ENTITY enginecontrol IS PORT (clk,button: IN BIT; engine: OUT BIT); END enginecontrol; ARCHITECTURE behavior OF enginecontrol IS TYPE statesec IS (A,B,C,D); SIGNAL state: statesec:=A; BEGIN PROCESS (clk) BEGIN IF (clk'EVENT AND clk ='1') THEN CASE state IS WHEN A => IF button ='0' THEN state<=B; ELSE state<=A; END IF; WHEN B => IF button ='1' THEN state<=C; ELSE state<=B; END IF; WHEN C => IF button ='0' THEN state<=D; ELSE state<=C; END IF; WHEN D => IF button='1' THEN state<=A; ELSE state<=D; END IF; END CASE; END IF; END PROCESS; engine<= '0' WHEN state=A ELSE '1' WHEN state=B ELSE '1' WHEN state=C ELSE '0'; END behavior;Here, remember, button pushed is 0 and button released is 1. Engine 'on' is 1 and engine 'off' is 0.  

This code, I believe, clearly describes a state machine with four possible states. It starts at state A, with the engine off. If the button is pushed, it goes to state B, and the engine turns on. It will remain on state B as long as the button is pushed, and when the button is released, it goes to state C, engine still on. Push the button again, and you get state D, engine off. Let it go and the cycle begins again, at state A. 

This is the desired behavior! Always the same, reliable... 

 

But the real behavior is... random! Around 70% of the time, when you release a button, it goes from state B to A, instead of C, or from state D to C, instead of A. This, of course, has undesired results on the output. Nowhere in the code I can see anything that could produce this behavior! And around 30% of the time, releasing a pushed button works as intended, and the machine goes to the correct next state. Since I won't be seeing my lab professor again until January 10th, can you guys tell me why this is happening? 

Many thanks for your time and help!
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
1,273 Views

According to your spec I don't need state machine just toggle a register upon push. 

 

Regarding you state transitions, remeber push is momentary and may suffer bouncing. you can add debouncing logic.
0 Kudos
Altera_Forum
Honored Contributor II
1,273 Views

I assume by bouncing you mean the fact that you can push the button just for a moment, but several '0' signals are sent, instead of just one. Yes, I knew and explained that... This is why if I only used a toggle, the circuit would never work as intended. The state machine I made is my way of filtering off that bouncing, it is my 'debouncing logic'. Why doesn't it work? Could you explain to me how would you do it instead?  

Many thanks!
0 Kudos
Altera_Forum
Honored Contributor II
1,273 Views

Or you mean that sometimes the button sends '0' signals even after being released already? Even after having sent some '1' -I'm released!- signals, a rogue '0' signal can come after that?? 

If that's the case... I have no idea how to overcome it.
0 Kudos
Altera_Forum
Honored Contributor II
1,273 Views

There are different ways to debounce keys. 

In your case you want to detect push = '0' once only over some practical interval. For example I will run a counter for 20 msec. 

 

pseudocode, on the clock edge... if push = '0' and count = max then -- first push detection push_L <= '1'; end if; if push = '0' and push_L = '0' then count <= 0; end if; if count < max then count <= count + 1; else push_L <= '0'; end if; if push = '0' and push_L = '0' then push_T <= not push_T; -- to your engine, hopefully without smoke end if; you will need to test this logic as I wrote it off head.
0 Kudos
Altera_Forum
Honored Contributor II
1,273 Views

You can also use your state machine for debouncing but add extra interval of time. This could be simpler to control: 

 

s0: detect push = 0, decide toggle, move to s1 

s1: stay for some time ignoring key, then move to s0
0 Kudos
Altera_Forum
Honored Contributor II
1,273 Views

The second solution you suggested was perfect. I added a counter to lock each state upon arrival for 100 mseconds, staying just there and ignoring all button input during this small lock interval. Now the machine works 100% as intended. 

 

Thanks a lot for your help! You've made an student happy!
0 Kudos
Reply