I have a simple board with 6 buttons, consisting of 3 columns and 2 rows I would like to detect the pressed button. My code below works with this fsm:
scan_fsm : process (reset, clk)
begin -- process key_scanner
if reset = '1' then
Send <= '0';
fsm_state <= start;
scannel_val <= "0000";
elsif clk'event and clk = '1' then
if state_inc = '1' then
scan_complete <= '0';
case fsm_state is
when start =>
Send <= '0';
scannel_val <= "0000";
my_switch <= "001";
fsm_state <= state1;
when state1 =>
case bcd_val is
when "01" =>
Send <= '1';
scannel_val <= "0001";
when "10" =>
Send <= '1';
scannel_val <= "0010"; -- Value 2
when others =>
scannel_val <= "0000";
Send <= '0';
end case;
my_switch <= "010";
fsm_state <= state2;
when state2 =>
case bcd_val is
when "01" =>
Send <= '1';
scannel_val <= "0011";
when "10" =>
Send <= '1';
scannel_val <= x"0100"; -- Value 4
when others =>
scannel_val <= "0000";
Send <= '0';
end case;
my_switch <= "100";
fsm_state <= state3;
when state3 =>
case bcd_val is
when "01" =>
Send <= '1';
scannel_val <= "0101";
when "10" =>
Send <= '1';
scannel_val <= "0110";
when others =>
scannel_val <= "0000";
Send <= '0';
end case;
my_switch <= "001";
fsm_state <= state1;
scan_complete <= '1';
when others => scannel_val <= "0000";
end case;
end if;
end if;
end process scan_fsm;
I have 4 states, start and a state for each column. I would like to improve my board and prevent glitches. I would like to add fatures like if 2 buttons pressed at the same time, I should get the first value which reached few miliseconds or nanoseconds before the other one. Also I would like to prevent a second value being read or a third when already a button is being pressed.
So, no matter how many buttons pressed, only one value should be read. I thought about adding a 5th state, idle, when this occurs but then how do I get out of idle?
Instead of idle I can also switch to state "start" but then this would make the send
signal "0" which would be false if already a button is being pressed. Also how many processes are in this FSM? What is a process in VHDL? Is it 3; reset, clk and state_inc? statce_inc becomes "1" every 200Hz with the help of a counter. I added some debouncing code I found from the internet but doesn't help 🙁 Anyone has a debouncing suggestion?
Another issue, I would like to get rid of the state start
actually, the only reason I have it is because I should assign my_switch
to "001"
before state1
. In my first implementation I was assigning my_switch
to "001"
in state1
and "010"
in state2
and "100"
in state3
. In this implementation since my keypad is
______
|1|2|3|
|4|5|6|
When I pressed 2, 1 was displayed when I press 3, 2 was displayed. I was thinking Cpp/Java way but I was wrong… then I added a dummy state start
just to set my_switch
before entering the real scanning… So if I can solve this I can also save a state! Suggestions are welcome! I solved this with entering the first scan without a set value. Do you have better ideas?
Best Answer
What you can do is create an idle state, and when you detect a button press you switch straight to the idle. Then you can have a counter in idle which waits for a while before you start scanning buttons again.
For example:
There is one process in this code you've posted.
It starts with
and ends with
The clock and reset are part of the sensitivity list. That means that this code is only going to be triggered when either clock changes or reset changes.
De-bouncing can be done in a separate process. Basically, you want to make sure that the button was pressed for a number of microseconds before it triggers. What we want to do is save the value of the input for a number of clock cycles. Then only register a 1 when the history has been constantly 1 for for the past 32 clock cycles.
Example: