Kanupriya

To Remove Debounce from MicroJoystick installed on LogicStart MegaWing (FPGA) and read input correctly

Recommended Posts

I am coding in Verilog. I am trying to use the MicroJoystick installed on LogicStartMegaWing, the shield with Papilio-One 500k (my FPGA board). I have to do simple tasks like increment or decrement a reg variable on different movements of the joystick. Initially I was running the above code in an alwaya @ (SWITCH) block i.e. the block will be running whenever there is a movement in joystick (on this board joystick shares the pins with five switches). This led to complete loss of control of the cursor on the VGA display (very fast multiple increments or decrements), even on slightest movement of the joystick.

Then I ran the same code in an always @ (slowclk) block where 'slowclk' is a 1Hz clock. This led to improvement as there were finite, slower increments or decrements. However, the problem is not completely resolved i.e. on one move of the joystick there are multiple increments to the reg.

How can I remove this debounce from the input through the joystick? Need some help on this. I am also putting my code to generate the slowclk and to use the joystick.

 

 

///////////////

 

module Slowclock( input clk_25, output reg slowclk );

 

reg [63:0] i;

parameter delay = 12500000;

 

initial

begin

  slowclk = 0;
  i = 64'd0;

end

 

always @ (posedge clk_25)

begin

if (i < delay)

   i= i+1;

else

   begin
   i = 64'd0;
   slowclk = ~slowclk;
   end

end

endmodule

 

/////////////

 

 

always @ (slowclk)

begin

if (SWITCH[0]==0)

 if (I==0)
   I <= 3'd5;
 else
   I <= I - 1;

if (SWITCH1]==0)

 if (I==5)
   I <= 3'd0;
 else
   I <= I+1;

if (SWITCH[3]==0)

 if (J==5)
   J <= 3'd0;
 else
   J <= J + 1;

if (SWITCH[4]==0)

 if (J==0)
   J <= 3'd5;
 else
   J <= J - 1;

end

 

//////////////

Share this post


Link to post
Share on other sites

There are many references on the web for accomplishing this. Most use a counter and clock to establish a debounce interval. Another option is a shift register with an appropriate clock input.

 

As an example from the web, here is a switch debouncer using a shift register. I like the simplicity.

module debouncer (noisy,clk_1KHz,debounced);  input wire clk_1KHz, noisy;  output reg debounced;  reg [7:0] reg;  // wait for stable before reporting transition  always @ (posedge clk_1KHz)  begin    reg[7:0] <= {reg[6:0],noisy}; //shift register    if(reg[7:0] == 8'b00000000)      debounced <= 1'b0;  // has been 0 for 8 or more clocks    else if(reg[7:0] == 8'b11111111)      debounced <= 1'b1;  // has been 1 for 8 or more clocks    else      debounced <= debounced;  // do not update when bounce detected  endendmodule

Enjoy,

Bill

 

Share this post


Link to post
Share on other sites

Hi Kanupriya,

 

Looking at your code you are reading the switches once every 500 ms so the problem you are seeing is not due to classic "switch bounce", i.e. rapid opening and closing of the switch as the switch is activated. Switch bounce time is dependent on the switch design and is typically about 20 ms or less.

 

You stated that the problem is "on one move of the joystick there are multiple increments to the reg".  Based on the code you are incrementing or decrementing I or J once every 500 ms as long as the switch is activated so yes, one move of the joystick could lead to multiple increments to the reg if you keep it activated for more than 500 ms.  If you want only one increment or decrement every time a switch is activated then you need to detect the change from inactive to active and only increment/decrement when a change is detected.

 

A few comments on your code (hope you don't mind):

1) "always @ (slowclk)" means that you are sampling at both rising and falling edge of the clock, i.e. every 500 ms.

 

2) You are creating a new clock domain slowclk at 1 Hz so you now have two clock domains at 25 MHz and 1 Hz.  This is not really what you want (multiple clock domains require very special attention on signals that go between the clock domains).  It's better to clock everything at 25 MHz and have a sample enable at 1 Hz for the switch sampling.  I.e. something like this:

 

always @ (posedge clk_25)

begin

if (i < delay)

   begin

   i <= i+1;

   sample_en <= 1'b0;

   end

else

   begin
   i <= 64'd0;
   sample_en <= 1'b1;
   end

end

 

always @ (posedge clk_25)

if (sample_en)

   begin

   if (SWITCH[0]==0)

   ...

 

3) Instead of sampling the switches at 1 Hz I would do a real switch debounce,  This is typically done by sampling the switches every millisecond and only accept a new switch state if the sampling of the switches have been identical for n samples, where n is dependent on the switch bounce time.  Something like this will debounce all 5 switches in the joystick (n = 20):

 

always @ (posedge clk_25)

begin

if (i < 25000)

   begin

   i <= i+1;

   debounce_en <= 1'b0;

   end

else // one millisecond has passed

   begin
   i <= 15'd0;
   debounce_en <= 1'b1;
   end

end

 

reg [4:0] last_switch, debounced_switches;

 

always @ (posedge clk_25)

if (debounce_en) // time to check the switches

   begin

   if (SWITCH != ~last_switch) // joystick SWITCH state has changed

      begin

      last_switch <= ~SWITCH; // save the compliment of SWITCH, last_switch is now active-high

      n <= 20;

      end

   else if (n > 0) // not debounced yet

      n <= n - 1;

   else

      debounced_switches <= last_switch; // SWITCH have been stable for 20 samples, accept the new switch state

   end

 

4) if you want to act only once on each switch activation the you could do something like this:

 

reg [4:0] old_debounced_switches;

 

always @ (posedge clk_25)

if (debounced_switches != old_debounced_switches) // debounced switch state change detected, act on the switch state change

begin

   old_debounced_switches <= debounced_switches;

   if (debounced_switches[0]==1 && old_debounced_switches[0] == 0) // switch 0 has changed (to active state)

      if (I==0)
         I <= 3'd5;
      else
         I <= I - 1;

...

end

 

Hope this helps,

Magnus

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now