Presionando las mismas filas de teclas al mismo tiempo

Estoy diseñando un teclado en VHDL. Todo funciona bien cuando solo se presiona una tecla. Estoy escaneando cada columna para presionar una tecla en una máquina de estado y cuando no se presiona ninguna tecla, que es la condición en la pin4pin6pin7pin2 = "0000"que cambio al siguiente estado para escanear la siguiente columna. Por lo tanto, configuré las columnas pin3pin1pin5secuencialmente en "001", "010"y "100".

Mientras escanea pin3pin1pin5como "001"y si pin4pin6pin7pin2es "0100"entonces simplemente se presiona "9". Declaro en VHDL pin4pin6pin7pin2como puertos de entrada y pin3pin1pin5como de salida. Cuando presiono 6 y 9 al mismo tiempo pin6y pin7son high. Se lee la primera tecla pulsada, se ignora la segunda. Cuando presiono 3 y 7 al mismo tiempo, el primero presionado con unos ms antes gana y se lee la primera tecla, la segunda tecla se ignora pin2y pin4son high.

He aquí la parte complicada. Cuando presiono 4 y 6 al mismo tiempo, espero pin7que sea high, pero se convierte en lowy pin4pin6pin7pin2 = "0000", que no entiendo cómo ni por qué. Debido a que "0000"se detecta que no se presionó ninguna tecla, la máquina de estado salta de un estado a otro. Mientras se mantiene presionado 4 y 6 si uno presiona y deja 4 varias veces, se detecta como 6 presionado varias veces, lo cual es un gran error . ¡Me encantaría que me ayudaran a depurar esto!

Lo mismo sucede con "1" y "2", lo mismo con "7" y "8" solo para las teclas en la misma fila. Dado que este es un proyecto en curso, no puedo poner mi código VHDL en línea :( ¡Me encantaría que me diera consejos para superar esto!

ingrese la descripción de la imagen aquí

A continuación, no estoy cargando mi código en el tablero, no se está ejecutando ningún código. Conectando Pin5a tierra, una sola pulsación en 1,2,4,5,7,8,*,0 no enciende Pin3el LED, pero si presiono 6 y luego 4 al mismo tiempo , el Pin3LED está encendido y el Pin7LED sigue encendido, pero cuando mi código se está ejecutando esto no sucede. A lo mejor conecté algo mal y por suerte Pin7está encendido, no sé...

ingrese la descripción de la imagen aquí

A continuación se muestra el esquema de la placa del teclado:

esquemas

¿Cómo se asegura de que al presionar 4 y 6 al mismo tiempo no se cortocircuiten los pines 3 y 5?
@ fru1tbat ¿Puedes elaborar un poco más en corto? Sin cargar mi código cuando la placa no tiene nada encendido, conecto el pin5 a tierra, luego el LED del pin5 se enciende y luego presiono "6" el LED del pin7 se enciende luego presiono "4" y "6" al mismo tiempo esta vez pin3 El LED está encendido y el LED pin7 aún está ENCENDIDO.
@ Tut, ¿quieres decir que debería usar pull-up para filas y pull up para columnas? No puedo modificar el circuito. Tampoco entendí mucho de tu comentario :(
Para ser más completo, proporcionaré una respuesta. Sería útil si pudiera proporcionar un esquema que muestre resistencias, LED, controladores de columna y cualquier inversor o transistor que pueda estar en el circuito. ¿Las 4 filas y las 3 columnas están conectadas directamente a un CPLD o FPGA?
@Tut El teclado no está conectado directamente a la FPGA, hay otra placa en el medio, para conectar varias placas a la FPGA y agregué los esquemas.
En la placa FPGA, ¿las 7 señales asociadas con el teclado (3 selecciones de columna y 4 señales de fila) están directamente conectadas a los pines del conector (conector 2 en el esquema anterior)? Si ese es el caso, siga las instrucciones en mi respuesta utilizando la lógica de drenaje abierto para las salidas de selección de columna en su FPGA.
También tenga en cuenta que en su esquema, todos los LED se muestran cableados al revés. Los ánodos van a las resistencias limitadoras de corriente y los cátodos van a las líneas de señal. Los LED se encienden cuando las líneas de señal se bajan.
@Tut solo 3 columnas, 4 filas están conectadas al FPGA que es lo que tengo en mi archivo UCF y, por supuesto, el CLK.
OK gracias. Mantengo mi respuesta, uso la lógica VHDL de drenaje abierto para las salidas de selección de columna.

Respuestas (3)

La respuesta corta:

Invierte tu lógica. Conduzca las líneas de selección de columna con lógica de drenaje abierto (o colector abierto) donde la columna seleccionada se baja y las columnas no seleccionadas están flotando. Cuando mira una fila, la pulsación de una tecla se detectará con un '0'. Las teclas no presionadas serán detectadas por un '1'.

Ahora los detalles:

Como señala EEIngenuity, cuando presiona 2 botones en la misma fila, se produce un cortocircuito entre sus columnas correspondientes. Este (y otros problemas que involucran múltiples pulsaciones de teclas) generalmente se resuelven en una matriz de teclado agregando un diodo en serie con cada interruptor.

Dado que agregar diodos no es una opción para usted, deberá hacer flotar las salidas de sus selecciones de columna inactiva para evitar intentar llevarlas a la polaridad opuesta a la selección de su columna activa. Esto se hace usando la lógica de drenaje abierto. Si sus selecciones de columna están vinculadas directamente a un CPLD o FPGA, debería poder lograr esto en su código VHDL.

La foto en su pregunta muestra que tiene una resistencia pull-up en cada columna y cada fila. Los pull-ups en las columnas son innecesarios, pero no dañarán nada. Los pull-ups en cada fila asegurarán una condición alta a menos que el impulsor de drenaje abierto en las selecciones de la columna tire hacia abajo (a través de un interruptor cerrado).

Tuve que hacer algunas suposiciones sobre su circuito ya que no proporcionó un esquema completo o su código VHDL. Tu dices

cuando no se presiona ninguna tecla, que es la condición pin4pin6pin7pin2 = "0000"

sin embargo, a partir de la foto que proporciona, se muestran las resistencias pull-up. Esto implica que ya tiene una inversión lógica en alguna parte, posiblemente en su código VHDL o (menos probable) inversores entre sus filas y su dispositivo lógico (CPLD o FPGA).

Editar:

Según su comentario, está utilizando lógica negativa en sus descripciones: "0000" indica que los cuatro pines están altos, etc. Siendo ese el caso, asumiendo que las selecciones de columna y las señales de fila van directamente desde el conector 2 en su esquema al FPGA, solo siga mis instrucciones anteriores utilizando la lógica de drenaje abierto para las salidas de selección de columna en su FPGA.

No soy un experto en VHDL, pero encontré esto de Xilinx :

Infiere el búfer de drenaje abierto usando el siguiente código:

VHDL:

dout <= 'Z' when din='1' else '0';

También tenga en cuenta que en su esquema, todos los LED se muestran cableados al revés. Los ánodos van a las resistencias limitadoras de corriente y los cátodos van a las líneas de señal. Los LED se encienden cuando las líneas de señal se bajan.

Estoy a punto de escanear los esquemas instalando el controlador del escáner
Tienes razón acerca de pin4pin6pin7pin2 = "0000"que ninguna pulsación de tecla es en realidad 1111. En mi pregunta, los 1 deberían ser 0, los 0 deberían ser 1, traté de encriptar un poco la pregunta, lo siento si causó malentendidos...
Agregué los esquemas.
muchas gracias por sus explicaciones, después de leer su respuesta, tengo algunas ideas, pero primero, ¿qué quiere decir con "las columnas están flotando", "necesita flotar las salidas", por flotar quiere decir: 110, 101, 011? Esto ya lo estoy haciendo, en realidad en mi código cuando se presiona una tecla, todas las demás teclas deben ignorarse. Simplemente no entiendo cómo se apaga el LED y pin7 se vuelve alto (1), mientras se ejecuta el código. De todos modos, si entendí que es correcta, su solución sugiere que mientras estoy escaneando pin5, puertos de salida "110", debería haberlo hechoout <= 'pin3' when din='1' else '0';
Mire el enlace que proporcioné: drenaje abierto (o colector abierto) . La columna activa se selecciona conduciendo 0V en esa línea de columna. Las columnas inactivas NO deben funcionar con 3,3 V en esa línea, sino que deben flotar (ponerse en un estado de alta impedancia) que desconecte efectivamente esas líneas del circuito. Si intenta llevarlos a 3,3 V, el cortocircuito creado al presionar 2 botones en la misma fila al mismo tiempo provocará una contienda entre uno que intenta conducir bajo y los otros que intentan conducir alto.
Lo que estoy sugiriendo es algo como: pin3_out <= 'Z' when pin3_internal = '1' else '0'; ... La 'Z' especifica que la salida es flotante (no impulsada) cuando su lógica interna es '1'
pin3_internalprobablemente será un puerto de salida, y no es posible leer los puertos de salida en VHDL. Además, ¿qué es "Z"? ¿Una pequeña señal? No entiendo ese whencaso, el normal que conozco es como:output <= in0 WHEN "00",
Lo llamé pin3_internal para que no lo confundiera con su pin de salida, al que llamé pin3_output (pin3_internal NO es un pin de salida, sino que proviene de su lógica interna). Como dije, no soy un experto en VHDL. Normalmente codifico en Verilog. Mi ejemplo vino de Xilinx. 'Z' es un valor válido (alta impedancia) en VHDL para std_logic . Creo que es posible que deba estudiar su VHDL. No creo que pueda explicarlo mejor.
Investigué un poco más sobre el colector abierto, y esta definitivamente es la respuesta a mi problema, pero aún no sé cómo implementarlo, también entiendo ahora el código pin3_out <= 'Z' when pin3_internal = '1' else '0';si tuviera paréntesis, lo entendería más rápido :) Esto significa cuando Estoy comprobando pin5que debería flotar pin3y pin1, así que creo que debería hacer esto en la misma línea donde estoy configurando pin3pin1pin5 <= "110"y pin3_internalaquí pin3_out <= 'Z' when pin3_internal = '1' else '0';no hay ninguno de los pin2, pin7, pin6, pin4. ¿Dónde debo pin3_internaltrabajar?
Después de probar algunas variaciones, lo descubrí, muchísimas gracias, eres una leyenda =) ¡el código de coleccionista abierto que diste funcionó!
Ahora estoy escribiendo una documentación sobre mi circuito, también debo mencionar esta solución, ¿el pin7 va directamente a tierra cuando el pin3 y el pin5 tienen VDD al mismo tiempo? Lo resolvemos invirtiendo el pin3 deteniendo el flujo de voltaje, ¿entendí correctamente? ? Este método se llama colector abierto, ¿se usa para resistencias pull-up? Si fuera desplegable, 1 sería alto en nuestro caso y necesitaríamos dout <= 'Z' when din='0' else '1';. Sé que escribiste mucho, pero ¿podrías elaborar la solución un poco más para mí?

Como está utilizando VHDL y tiene una entrada asíncrona, escribo esta respuesta para asegurarme de que tomó precauciones. No estoy seguro de si este es tu problema, pero muy bien podría serlo.

Vea una pregunta que hice hace algún tiempo: VHDL: el módulo de recepción falla aleatoriamente al contar bits

Ahora, dices que:

Debido a que "0000" se detecta como una tecla sin presionar, la máquina de estado salta de un estado a otro. Mientras se mantiene presionado 4 y 6, si uno presiona y deja 4 varias veces, se detecta que 6 se presionó varias veces, lo cual es un gran error.

Lo cual es algo similar a lo que estaba enfrentando. Tuve un problema en el que mi máquina de estado saltaba estados, lo que parecía imposible.

Si lee las respuestas a la pregunta vinculada anteriormente, verá que se recomienda agregar un sincronizador a la línea de entrada antes de que se introduzca en su máquina de estado. Esto generalmente se logra con dos D Flip Flops en serie:

ingrese la descripción de la imagen aquí

No tener la entrada de su botón sincronizada con su HW causa problemas muy extraños, que he experimentado con mi proyecto N64. Agregar este poco de HW fue casi como magia.

Por lo tanto, verifique primero que sus entradas se estén sincronizando.

Implementar el Sincronizador en la respuesta no parece dificil pero cuando leo el proceso lo que entiendo es que async_inse retrasa con 3 ciclos de reloj pero su valor y todo es igual?
La gran diferencia es que su señal se convertirá de asíncrona a síncrona. Lo que sucede en HW a veces con señales asíncronas (como tus botones) es que los bits están en "meta-estabilidad", esto provoca errores muy extraños en el HW. El uso de las chanclas D garantiza que no se produzca metaestabilidad en su diseño. También era escéptico sobre la efectividad de esto, pero resolvió mi problema perfectamente.
Lo probé, valió la pena intentarlo pero no ayudó :(

¡Esta es una pregunta interesante! La razón por la que ve un nivel bajo en el pin7 cuando presiona la tecla 4 y la tecla 6 es por el pin3 y el pin5.

Para explicar más, pin3 y pin5 nunca estarán altos al mismo tiempo; uno de ellos siempre será un camino a tierra (según su diseño). Por lo tanto, cuando presiona la tecla 4 y la tecla 6, está creando un camino a tierra para pin7.

Ver imagen:

El pin 7 ve un camino a tierra.  Tienes un cortocircuito.

Agregué una imagen a mi pregunta y pin7 aún se ve alto cuando se presionan ambas teclas.
OP explicó que no sube el pin 3, 1 o 5 ALTO al mismo tiempo en ningún momento. Él secuencia las columnas con: "001", "010" y "100". Para empezar, los pines 3 y 5 nunca están ALTOS simultáneamente.
Ese es el punto que @EEIngenuity está tratando de hacer: hay un camino aparente entre los pines 3 y 5, que nunca tendrá el mismo valor, "por lo tanto, cuando presiona la tecla 4 y la tecla 6, está creando un camino a tierra para pin7. "
@ fru1tbat Pero como ves en la imagen que subí, pin7 está encendido y no va a tierra. Pero digamos que se va a tierra, ¿entonces será imposible superar mi problema?
"Mientras se mantiene presionado 4 y 6, si uno presiona y sale 4 varias veces, se detecta como 6 presionado varias veces, lo cual es un gran error ". Parece que no está detectando "ninguna tecla presionada" entre las detecciones de teclas válidas.
@Anarkie En su nueva imagen, ¿sabría si esos LED respectivos están cableados: (a) serie entre el botón y el terminal dorado o (b) paralelo entre el terminal y tierra ? Dado que la terminal dorada está flotando y los LED aún se encienden, parecería que esos LED están colocados en paralelo entre el interruptor y la tierra. Esa podría ser la razón por la que todavía se encienden durante esta combinación de entrada.
@EEIngenuity Agregué los esquemas.
@Anarkie, como Tut mencionó en su respuesta, los LED están absolutamente dibujados al revés en el esquema. Pero, de hecho, están atados al nodo en paralelo. La versión de prueba "sin código cargado" funciona correctamente. ¿Has probado el evento de cortocircuito que sugerí en mi respuesta original? Si es así, ¿cómo lo hiciste?
La prueba que hice para el evento de cortocircuito es presionar 4 y 6 al mismo tiempo como ves en la imagen, de lo contrario no sé a qué te refieres.
@Anarkie En la imagen, Pin3 no está conectado a GND o VDD. Es un nodo flotante. Esto no crea el escenario de cortocircuito que tiene en su prueba original. Intente conectar el pin 3 a VDD y el pin 5 a GND y repita esta prueba.
@EEIngenuity ¡Tienes toda la razón! Sí, sí, cuando conecto pin3 a VDD, ¡pin7 se vuelve bajo! Entonces, ayúdenme, ¿cómo puedo superar este problema y hacer que funcione? ¡No sé cómo, el mismo teclado, la misma placa!