¿Por qué mi código de Verilog para la matriz de botones 4x4 no se está escaneando?

0

Tengo un problema con un módulo en Verilog donde necesito escanear una matriz de botones 4x4. No puedo escanear cada fila 1 por una, pero la cosa se queda con la primera fila. ¿Puedes ayudarme a depurarlo? A mi me parece lógicamente correcto.

El código es:

module keyboardScanner(input clk,input  [3:0] col, output reg [3:0] row,output reg [7:0] keyCode);
always @(posedge clk)begin
                row = 4'b1000;
                if(col != 4'b0000)begin
                        keyCode[0] = row[0];
                        keyCode[1] = row[1];
                        keyCode[2] = row[2];
                        keyCode[3] = row[3];
                        keyCode[4] = col[0];
                        keyCode[5] = col[1];
                        keyCode[6] = col[2];
                        keyCode[7] = col[3];
                end
                row = 4'b0100;
                if(col != 4'b0000)begin
                        keyCode[0] = row[0];
                        keyCode[1] = row[1];
                        keyCode[2] = row[2];
                        keyCode[3] = row[3];
                        keyCode[4] = col[0];
                        keyCode[5] = col[1];
                        keyCode[6] = col[2];
                        keyCode[7] = col[3];
                end
                row = 4'b0010;
                if(col != 4'b0000)begin
                        keyCode[0] = row[0];
                        keyCode[1] = row[1];
                        keyCode[2] = row[2];
                        keyCode[3] = row[3];
                        keyCode[4] = col[0];
                        keyCode[5] = col[1];
                        keyCode[6] = col[2];
                        keyCode[7] = col[3];
                end
                row = 4'b0001;
                if(col != 4'b0000)begin
                        keyCode[0] = row[0];
                        keyCode[1] = row[1];
                        keyCode[2] = row[2];
                        keyCode[3] = row[3];
                        keyCode[4] = col[0];
                        keyCode[5] = col[1];
                        keyCode[6] = col[2];
                        keyCode[7] = col[3];
                end
    end
endmodule // keyboardScanner
    
pregunta anon

2 respuestas

3

Parece que estás un poco confundido acerca de lo que hace un bloque always .

Cada vez que hay un posedge clk , TODAS las sentencias dentro del bloque se ejecutan, y la última asignación a cada señal es la que se aplica. Todas las demás afirmaciones anteriores se ignoran de forma efectiva.

Además, solo por concisión y legibilidad, no es necesario asignar cada bit de un campo de múltiples bits por separado. Podrías escribir

keycode[3:0] <= row[3:0];
keycode[7:4] <= col[3:0];

o incluso simplemente

keycode <= {col, row};

Finalmente, también querrá agregar una salida "estroboscópica" o "válida" para indicar cuándo se está presionando una tecla (vs. no se presionó ninguna tecla). De lo contrario, no podrá detectar la misma tecla presionada dos veces seguidas.

EDITAR:

Para poder hacer algo secuencialmente en hardware, necesitas configurar una máquina de estado. En este caso, la variable row puede ser su variable de estado. Por ejemplo:

module keyboardScanner (
  input            clk,
  input            reset,       /* additional input */
  input      [3:0] col,
  output reg [3:0] row,
  output reg [7:0] keyCode,
  output reg       keyValid     /* additional output */
);

  always @(posedge clk) begin
    if (reset) begin
      /* Reset all register variables.
       * Not strictly necessary for synthesis,
       * but the simulator will require it.
       */
      row <= 4'b1000;
      keyCode <= 8'b0;
      keyValid <= 0;
    end else begin
      /* If any column is active in the current row,
       * output the row and column pattern as a keyCode,
       * and assert keyValid. Pause the scanning as long
       * as the key is held down.
       */
      if (col != 4'b0000) begin
        keycode <= {col, row};
        keyValid <= 1;
      end else begin
        keyValid <= 0;
        /* Scan the matrix, one row per clock period
         */
        case (row)
          4'b1000: row <= 4'b0100;
          4'b0100: row <= 4'b0010;
          4'b0010: row <= 4'b0001;
          4'b0001: row <= 4'b1000;
          default: row <= 4'b1000;
        endcase
      end
    end
  end

endmodule // keyboardScanner

EDIT 2

La primera versión del código que publiqué tenía un par de errores tipográficos, más un error real. Como se codificó originalmente, si se presionaba una tecla, la lógica emitiría una serie de pulsos keyValid tan rápido como el ciclo de exploración. Para solucionar este problema, lo más sencillo es pausar el escaneo cuando una tecla está presionada, como se muestra arriba.

El código revisado todavía no hace ningún rebote de las pulsaciones de teclas. También hay una forma sencilla de agregar eso, pero se deja como un ejercicio para el lector.

    
respondido por el Dave Tweed
2

Aquí, sin importar qué es la entrada col , el valor de row es siempre 4'b0001 . Dado que row se maneja desde múltiples lugares , en cada posición.

Creo que row debe manejarse desde dentro del bloque if(col != 4'b....) .

El siguiente es un error general. Es una buena práctica usar asignaciones no bloqueantes dentro del bloque always . Esto puede ayudar en la síntesis del diseño. Si ignora la directriz anterior, también puede inferir la lógica sintetizada correcta, pero la simulación previa a la síntesis podría no coincidir con el comportamiento del circuito sintetizado.

Para obtener más pautas, consulte this y this enlace.

    
respondido por el sharvil111

Lea otras preguntas en las etiquetas