Librería en VHDL para controlar un teclado matricial 4×4.
Un teclado matricial es un dispositivo que agrupa varios pulsadores conectados de tal forma que se optimiza el uso de pines del microcontrolador, al compartir un mismo nodo para las filas y un nodo para las columna, permite controlarlos empleando un número de conductores inferior al que necesitaríamos al usarlos de forma individual.
La librería Teclado Matricial permite controlar un teclado 4×4 y devuelve un valor de 4 bits indicando la tecla que se ha presionado.
Los puertos de la librería son:
FREQ_CLK: Puerto genérico en donde se especifica la frecuencia de reloj dada en Hertz.
CLK: Señal de reloj.
COLUMNAS: Puerto de 4 bits conectado a las columnas del teclado.
FILAS: Puerto de 4 bits conectado a las filas del teclado.
BOTON_PRES: Puerto de 4 bits que indica qué tecla se ha presionado.
IND: Bandera de un bit que indica cuando se ha presionado un botón. El pulso sólo dura un ciclo de reloj.
Para que la librería funcione se tiene que conectar el teclado de la siguiente forma:
Las filas se conectan directamente a los pines del FPGA y las columnas se conectan utilizando un arreglo de resistencias pull-down. La librería se encarga de multiplexar las filas e ir llenando un registro de corrimiento el cual elimina el efecto rebote provocado por el ruido que los botones generan al ser presionado. El tiempo total en el que el registro se llena es de 8ms.
Cada tecla cuenta con su propio registro de corrimiento.
SIGNAL REG_B1 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B2 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B3 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B4 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B5 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B6 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B7 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B8 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B9 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_BA : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_BB : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_BC : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_BD : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_B0 : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_BAS : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0'); SIGNAL REG_BGA : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'0');
Cuando un registro se ha “llenado” la bandera IND se pone a ‘1’, esta bandera es importante ya que nos indica cuando una tecla ha sido presionada y un dato ya es válido, el dato se mostrará en forma de un vector de 4 bits y saldrá por el puerto BOTON_PRES. En VHDL un vector puede ser representado en forma hexadecimal siendo cada dígito la representación de 4 bits. La siguiente tabla muestra el valor de cada uno de los botones.
En nuestro código en VHDL se tiene que hacer la instancia de la librería en el TOP de nuestro diseño, por ejemplo:
entity TOP_DIS is PORT( CLK : in std_logic; COLUMNAS : in std_logic_vector(3 downto 0); FILAS : out std_logic_vector(3 downto 0); TRANSISTOR : out std_logic_vector(3 downto 0); DISPLAY : out std_logic_vector(7 downto 0) ); end TOP_DIS; architecture behavioral of TOP_DIS is component LIB_TEC_MATRICIAL_4X4_INTESC_REVA is generic( FREQ_CLK : integer := 50_000_000 ); port( CLK : in std_logic; COLUMNAS : in std_logic_vector(3 downto 0); FILAS : out std_logic_vector(3 downto 0); BOTON_PRES : out std_logic_vector(3 downto 0); IND : out std_logic ); end component LIB_TEC_MATRICIAL_4X4_INTESC_REVA; signal boton_pres : std_logic_vector(3 downto 0) := (others => '0'); signal ind : std_logic := '0'; begin u1 : LIB_TEC_MATRICIAL_4X4_INTESC_REVA generic map( FREQ_CLK => 50_000_000 ) port map( CLK => CLK, COLUMNAS => COLUMNAS, FILAS => FILAS, BOTON_PRES => boton_pres, IND => ind );
Un ejemplo de cómo utilizar la librería es crear un contador el cual se incrementará sólo si se presiona la tecla “*”, el código quedaría de la siguiente manera:
process(CLK) begin if rising_edge(CLK) then if ind = '1' and boton_pres = x"E" then conta_tecla <= conta_tecla + 1; if conta_tecla = 10 then conta_tecla <= 0; end if; end if; end if; end process;