Kanupriya Posted June 21, 2014 Report Share Posted June 21, 2014 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; initialbegin slowclk = 0; i = 64'd0;end always @ (posedge clk_25)beginif (i < delay) i= i+1;else begin i = 64'd0; slowclk = ~slowclk; endendendmodule ///////////// always @ (slowclk)beginif (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 ////////////// Link to comment Share on other sites More sharing options...
bgreat Posted June 21, 2014 Report Share Posted June 21, 2014 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 endendmoduleEnjoy,Bill Link to comment Share on other sites More sharing options...
mkarlsson Posted June 21, 2014 Report Share Posted June 21, 2014 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)beginif (i < delay) begin i <= i+1; sample_en <= 1'b0; endelse begin i <= 64'd0; sample_en <= 1'b1; endend 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)beginif (i < 25000) begin i <= i+1; debounce_en <= 1'b0; endelse // one millisecond has passed begin i <= 15'd0; debounce_en <= 1'b1; endend 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 changebegin 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 Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.