Para eliminar el rebote de MicroJoystick instalado en LogicStart MegaWing (FPGA) y leer la entrada correctamente

0

Estoy trabajando en una placa FPGA y codificación en Verilog. Estoy tratando de usar el MicroJoystick instalado en LogicStartMegaWing, el escudo con Papilio-One 500k (mi placa FPGA). Tengo que hacer tareas simples como aumentar o disminuir una variable de registro en diferentes movimientos del joystick. Inicialmente, estaba ejecutando el código anterior en un bloque alwaya @ (SWITCH), es decir, el bloque se ejecutará siempre que haya un movimiento en el joystick (en este tablero el joystick comparte los pines con cinco interruptores). Esto llevó a la pérdida completa del control del cursor en la pantalla VGA (incrementos o decrementos múltiples muy rápidos), incluso con el menor movimiento del joystick.

Luego ejecuté el mismo código en un bloque always @ (slowclk) donde 'slowclk' es un reloj de 1Hz. Esto condujo a una mejora, ya que hubo incrementos o decrementos finitos y más lentos. Sin embargo, el problema no se resuelve completamente, es decir, en un solo movimiento del joystick hay varios incrementos en el registro.

¿Cómo puedo eliminar este rebote de la entrada a través del joystick? ¿Necesitas ayuda en esto? También estoy poniendo mi código para generar el slowclk y para usar el joystick.

EL CÓDIGO REVISADO COMPLETO:

 //This increments/decrements number and displays on seven segment display on
 //up/down movement of joystick; in an array of 8 LEDS shifts the glowing LED to
 //right or left on left/right movement of joystick

 //joystick (i.e. [4:0] SWITCH here) by default gives all ones

 // input clock is at 32 Mhz

module Display(

input clk,
input [4:0] SWITCH,
output reg [3:0] Seg7_AN,
output reg Seg7_A,
output reg Seg7_B,
output reg Seg7_C,
output reg Seg7_D,
output reg Seg7_E,
output reg Seg7_F,
output reg Seg7_G,
output Seg7_DP,
output reg [7:0] LED
);

reg [3:0] number;
wire [4:0] clean;

Debounce stable(.clk(clk), .SWITCH(SWITCH), .clean(clean));

initial
begin
LED = 8'b00000001;
end

assign Seg7_DP = 1;

always @ (clean)
begin
if(clean[0]==0)
  begin
  if (number==9)
    number <= 0;
  else
    number <= number+1;
  end
else if (clean[1]==0)
begin
if (number==0)
   number <= 9;
else
   number <= number -1;
end
else if (clean[3] == 0)
begin
   if (LED == 8'b00000001)
      LED <= 8'b10000000;
   else
      LED <= LED >> 1;
   end
   else if (clean[4]==0)
   begin
     if (LED == 8'b10000000)
        LED <= 8'b00000001;
     else
        LED <= LED << 1;
end
end

always @ (*)
begin

   Seg7_AN <= 4'b0111;

case (number)
0 : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=0 ; Seg7_F<=0 ; Seg7_G<=1 ; end
1 : begin Seg7_A<=1; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=1 ; Seg7_E<=1 ; Seg7_F<=1 ; Seg7_G<=1 ; end
2 : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=1 ; Seg7_D<=0 ; Seg7_E<=0 ; Seg7_F<=1 ; Seg7_G<=0 ; end
3 : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=1 ; Seg7_F<=1 ; Seg7_G<=0 ; end
4 : begin Seg7_A<=1; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=1 ; Seg7_E<=1 ; Seg7_F<=0 ; Seg7_G<=0 ; end
5 : begin Seg7_A<=0; Seg7_B<=1 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=1 ; Seg7_F<=0 ; Seg7_G<=0 ; end
6 : begin Seg7_A<=0; Seg7_B<=1 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=0 ; Seg7_F<=0 ; Seg7_G<=0 ; end
7 : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=1 ; Seg7_E<=1 ; Seg7_F<=1 ; Seg7_G<=1 ; end
8 : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=0 ; Seg7_F<=0 ; Seg7_G<=0 ; end
9 : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=1 ; Seg7_F<=0 ; Seg7_G<=0 ; end
default : begin Seg7_A<=0; Seg7_B<=0 ; Seg7_C<=0 ; Seg7_D<=0 ; Seg7_E<=0 ; Seg7_F<=0 ; Seg7_G<=1 ; end 
endcase

end



endmodule





module Debounce(

     clk, SWITCH, clean
    );

input wire clk;
input wire [4:0] SWITCH;
output reg [4:0] clean = 0;

reg [18:0] count = 0;
reg [4:0] new = 0;

SlowClock OneKHz (.clk(clk), .slowclk(slowclk));

always @(posedge slowclk)
begin

    if (SWITCH != new)
    begin                                
        new <= SWITCH;
        count <= 0;
    end
    else if (count == 20) 
     begin
             clean <=new;  
             count <=0; 
     end        
    else                                 
        count <= count+1;
end

 endmodule


module SlowClock(
    input clk,
    output reg slowclk
    );

reg [63:0] i;

parameter delay = 32000;

initial
begin
    slowclk = 0;
    i = 64'd0;
end

always @ (posedge clk)
begin
if (i<delay)
    begin
    i= i+1;
    end
else
    begin
    i = 64'd0;
    slowclk = ~slowclk;
    end
end


endmodule
    
pregunta Kanupriya

3 respuestas

2

El rebote, como estoy seguro de que está al tanto, ocurre cuando los contactos de un interruptor o botón literalmente rebotan entre sí cuando lo activa. Esto causa, cuando se trabaja digitalmente, una sucesión rápida de señales de encendido-apagado-encendido-apagado-encendido, que finalmente termina con el estado estacionario que se pretende.

Hay dos métodos básicos de desalojo (encendido: eliminar el rebote): software y hardware. Los métodos de hardware se pueden dividir en dos tipos: filtros RC y flip-flops. Este último requiere una entrada de dos polos que se utiliza para alternar las entradas a un biestable biestable, y el primero trata la señal de conmutación como una forma de onda de CA y filtros de paso bajo que filtra el ruido de conmutación de alta frecuencia y deja el básico. Señales HIGH / LOW intactas).

Ninguno de los dos es realmente aplicable para escribir en Verilog, ya que no tiene condensadores, y su joystick no es un interruptor de dos polos, pero es útil conocer las opciones de hardware para que pueda ver cómo se relacionan. software.

El debouncing de software básicamente consiste en emular un filtro de paso bajo en el software. La forma más común de hacerlo es mirar la entrada y decir "¿Cuánto tiempo ha estado la entrada en este estado?", Y eso, por supuesto, requiere algún tipo de tiempo.

El método más simple es hacer lo siguiente:

  1. Observe cuando la entrada ha cambiado de estado
  2. Marca que ha cambiado y borra un contador.

Al mismo tiempo, controlado por el reloj, para cualquier entrada con el indicador "cambiado" establecido:

  1. Incrementa el contador de la entrada
  2. Si el contador supera un cierto límite, borre el indicador "cambiado" y establezca una variable de salida en el estado del conmutador.

Eso significa que cada vez que el interruptor cambia de estado, que será varias veces durante la presión de ese interruptor, el contador se borra, pero el indicador cambiado solo se establece una vez. Solo cuando se haya producido el último rebote, el contador podrá contar lo suficientemente alto (ya que el rebote restablece su valor) para superar el umbral, y solo entonces el estado de los conmutadores pasará al resto de su código.

El reloj quiere ser considerablemente más rápido que 1Hz. En general, se acepta que cualquiera de los dos eventos que suceden a más de 20 ms de distancia aparezcan (para nosotros) al mismo tiempo. Los 50 ms comienzan a ser realmente notables, por lo que un período de rebote de 10 a 20 ms suele ser bastante bueno. Por lo tanto, su reloj debe ir mucho más rápido que eso para incrementar el contador y dar una buena resolución de respuesta de la prensa. Para mantener las cosas simples, un reloj de 1KHz es bueno. Eso da una marca de 1 ms, por lo que cuando tu contador alcance 20, serán 20 ms y un buen umbral para tener.

    
respondido por el Majenko
2

Su problema no se trata de rebotar en absoluto. En realidad, se trata de cómo has codificado la segunda parte de tu listado. En lugar de buscar eventos de borde en los conmutadores, simplemente está probando su estado una vez por borde de reloj. Esto significa que en lugar de un incremento o decremento por operación de interruptor (que es lo que creo que quieres), obtienes un incremento o decremento por borde de reloj , siempre que se mantenga presionado el interruptor.

    
respondido por el Dave Tweed
0

imagen si tuvo una secuencia de señal en el tiempo como este 0000000000000000000010101010111111011111111111111 ¿Cómo podría detectar la transición de 0 a 1 una vez, pero dado que evidentemente podría volver a 0 en algún momento, esto solo debe ignorarse dentro de una ventana determinada?

Piense en el cambio de la señal como un "evento". También puede tener una "entrada de hardware" y una "entrada de rebote" donde la segunda es la señal aceptada que no fue solo el ruido del interruptor.

Lo primero que sucede es que puedes detectar el evento, independientemente del clima que ocurra varias veces. Me imagino que esto se puede hacer "guardando" la última entrada "rebatida" que se aceptó y asignó y comparando con la entrada actual del sistema.

Básicamente, está comprobando el tiempo en su entrada hace un ciclo de reloj es su entrada actual, desde aquí, puede generar una señal de activación que es utilizada por la lógica de rebote restante que determina la entrada "real".

Una implementación podría ser, por ejemplo, una máquina de estado si el hardware estuviera inactivo en un estado esperando el desencadenante anterior y realice la transición a un estado de espera durante un período de tiempo antes de volver al ralentí. Esto se puede implementar con una frecuencia de reloj conocida y un contador; al marcar el valor del contador, puede elegir cuándo volver del segundo estado al primero y repetir.

Si solo asigna la "entrada de hardware" a la "entrada con rebaje" cuando en el primer estado encontrará que la señal solo cambia tan rápido como la máquina de estado puede cambiar al segundo estado, contar y luego regresar a muestreo.

Creo que si tiene varias entradas (diferentes botones), es posible que se requiera que sean manejadas individualmente por instancias de un circuito como este.

    
respondido por el tjester

Lea otras preguntas en las etiquetas