Buscar este blog

sábado, 6 de junio de 2015

Unidad Aritmetica Logica en VHDL - Puerto PS2 (de 4 bits)

Programa main (Principal)

----------------------------------------------------------------------------------
-- Proyecto
-- Diseñar e implementar una unidad central de procesamiento en VHDL.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_arith.all;


ENTITY ALU IS
-- PARA EL TECLADO

    PORT ( CLK, CLC_E, R: IN STD_LOGIC;
 -- TECLADO
           PS2_CLOCK      : IN  STD_LOGIC;                     --clock signal from PS/2 keyboard
           PS2_DATOS      : IN  STD_LOGIC;                     --data signal from PS/2 keyboard
 -- LCD
 OP: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
 LCD_E, LCD_RS, LCD_RW : OUT STD_LOGIC;
 LCD_DB : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
 );
END ALU;

ARCHITECTURE CPU OF ALU IS

-- SEÑALES PARA LA ALU
SIGNAL A, B         : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL RES_OP       : STD_LOGIC_VECTOR(7 DOWNTO 0);

-- SEÑALES PARA LA LCD
SIGNAL E  : STD_LOGIC:= '0';
SIGNAL RS : STD_LOGIC:= '0';
SIGNAL RW : STD_LOGIC:= '0';
SIGNAL DB : STD_LOGIC_VECTOR(7 DOWNTO 0):= "00000000";

-- COMPONENTE TECLADO
COMPONENT TECLADOREAD IS
   PORT(   CLK        : IN STD_LOGIC;
   -- TECLADO
           ps2_clk    : IN  STD_LOGIC;                    
           ps2_data   : IN  STD_LOGIC;
           OUT1       : BUFFER STD_LOGIC_VECTOR(3 DOWNTO 0);
    OUT2       : BUFFER STD_LOGIC_VECTOR(3 DOWNTO 0));
 END COMPONENT;

-- COMPONENETE ALU
 COMPONENT ALUOPS IS
   PORT ( IN1      : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
        IN2      : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
TIP_OPER : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      RES      : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
 END COMPONENT;

-- COMPONENTE LCD
 COMPONENT LCDWRITE IS
   PORT( CLOCK  : IN STD_LOGIC;
     CLOCK_E: IN STD_LOGIC;
RESET  : IN STD_LOGIC;
INPUT1 : STD_LOGIC_VECTOR(3 DOWNTO 0);
INPUT2 : STD_LOGIC_VECTOR(3 DOWNTO 0);
OPER   : STD_LOGIC_VECTOR(3 DOWNTO 0);
S      : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
     LC_E   : OUT STD_LOGIC;
LC_RS  : OUT STD_LOGIC;
LC_RW  : OUT STD_LOGIC;
LC_DB  : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
 END COMPONENT;

FOR OPERACIONES_ALU : ALUOPS USE ENTITY WORK.ALUC(OPERACIONES);
FOR DESPLEGAR_LCD   : LCDWRITE USE ENTITY WORK.LCD(IMPRIMIR);
FOR LEER_TECLADO    : TECLADOREAD USE ENTITY WORK.DECODER(CODIFICACION);

BEGIN

-- LEER TECLADO
LEER_TECLADO : TECLADOREAD
PORT MAP( CLK=>CLK, ps2_clk=>PS2_CLOCK, ps2_data=>PS2_DATOS, OUT1=>A, OUT2=>B);

-- OPERACIONES DE ALU
OPERACIONES_ALU: ALUOPS
PORT MAP(IN1=>A, IN2=>B, TIP_OPER=>OP, RES=>RES_OP);

LCD_E  <= E;
LCD_RS <= RS;
LCD_RW <= RW;
LCD_DB <= DB;

-- PANTALLA LCD
DESPLEGAR_LCD : LCDWRITE
PORT MAP(CLOCK=>CLK, CLOCK_E=>CLC_E, RESET=>R, INPUT1=>A, INPUT2=>B, OPER=>OP, S=>RES_OP, LC_E=>E, LC_RS=>RS, LC_RW=>RW, LC_DB=>DB);

END CPU;


Operaciones de la ALU

----------------------------------------------------------------------------------
-- OPERACIONES DE LA ALU
----------------------------------------------------------------------------------
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;

entity ALUC is
    Port ( IN1, IN2, TIP_OPER : in  STD_LOGIC_VECTOR(3 DOWNTO 0);
       RES  : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
end ALUC;

architecture OPERACIONES of ALUC is
-- SEÑALES DE LA ALU
signal EA       : std_logic_vector(7 downto 0):="00000000";
signal EB       : std_logic_vector(7 downto 0):="00000000";
signal S        : std_logic_vector(7 downto 0):="00000000";

begin

-- ALU
EA <= "0000" & IN1;
EB <= "0000" & IN2;
PROCESS(TIP_OPER, EB, EA)
BEGIN
IF(TIP_OPER= "0000") THEN 
S<=EA+EB;           -- SUMA
ELSIF (TIP_OPER= "0001")THEN
S<=EA-EB;           -- RESTA
ELSIF(TIP_OPER="0010") THEN
S<=EA*EB;           -- MULTIPLICACION
ELSIF(TIP_OPER="0011") THEN        -- DIVICION 
     IF ((EA = "1111" and (EB = "1111" or EB = "1110" or EB = "1101" or EB = "1100" or EB = "1011" or EB = "1010" or EB = "1001" or EB = "1000"))
  or (EA = "1110" and (EB = "1110" or EB = "1101" or EB = "1100" or EB = "1011" or EB = "1010" or EB = "1001" or EB = "1000"))
or (EA = "1101" and (EB = "1101" or EB = "1100" or EB = "1011" or EB = "1010" or EB = "1001" or EB = "1000" or EB = "0111"))
  or (EA = "1100" and (EB = "1100" or EB = "1011" or EB = "1010" or EB = "1001" or EB = "1000" or EB = "0111"))
      or (EA = "1011" and (EB = "1011" or EB = "1010" or EB = "1001" or EB = "1000" or EB = "0111" or EB = "0110"))
      or (EA = "1010" and (EB = "1010" or EB = "1001" or EB = "1000" or EB = "0111" or EB = "0110"))
or (EA = "1001" and (EB = "1000" or EB = "0111" or EB = "0110" or EB = "0101"))
or (EA = "1000" and (EB = "0111" or EB = "0110" or EB = "0101"))
or (EA = "0111" and (EB = "0110" or EB = "0101" or EB = "0100"))
or (EA = "0110" and (EB = "0101" or EB = "0100"))
or (EA = "0101" and (EB = "0100" or EB = "0011")) 
or (EA = "0100" and EB = "0011") or (EA = "0011" and EB = "0010")) THEN
      S <="00000001";
  elsif ((EA = "1111" and (EB = "0111" or EB = "0110" or EB = "0101"))
      or (EA = "1110" and (EB = "1101" or EB = "0111" or EB = "0110" or EB = "0101"))
      or (EA = "1101" and (EB = "0110" or EB = "0101" or EB = "0100"))
      or (EA = "1100" and (EB = "0110" or EB = "0101"))
      or (EA = "1011" and (EB = "0101" or EB = "0100"))
      or (EA = "1010" and (EB = "0101" or EB = "0100"))
      or (EA = "1001" and  EB = "0100") 
or (EA = "1000" and (EB = "0100" or EB = "0011")) 
or (EA = "0111" and EB = "0011") 
or (EA = "0110" and EB = "0011") 
or (EA = "0101" and EB = "0010") 
or (EA = "0100" and EB = "0010")) then
S <= "00000010";
  elsif ((EA = "1111" and (EB = "0101" or EB = "0100"))
      or (EA = "1110" and EB = "0100")
or (EA = "1101" and EB = "0100")
      or (EA = "1100" and EB = "0100")
      or (EA = "1011" and EB = "0011")
      or (EA = "1010" and EB = "0011")
or (EA = "1001" and EB = "0011") 
or (EA = "0111" and EB = "0010") 
or (EA = "0110" and EB = "0010"))then
S <= "00000011";
 elsif ((EB = "0010" and (EA = "1001" or EA = "1000"))) then
S <= "00000100";
elsif ((EA = "1111" and EB = "0011")
  or  (EA = "1010" and EB = "0010")) then
S<= "00000101";
elsif(EA < EB or EA = "0000" or EB = "0000") then
S <= "00000000";
elsif(EA = EB) then
S <= "00000001";
elsif(EB = "0001") then
S(7 downto 0) <= EA;
else 
S<="00000000";
END IF;
ELSIF(TIP_OPER="0100") THEN                -- COMPLEMENTO A2
S<=("0001" & NOT(std_logic_vector(unsigned(EA(3 downto 0)))));           
ELSIF(TIP_OPER="0101") THEN 
S<=("0" & std_logic_vector(unsigned(EA(3 downto 0)) rol to_integer(unsigned(EB)))) and "01111"; -- ROTAR A LA IZQUIERDA
elsif (TIP_OPER="0110") then 
S<=("0" & std_logic_vector(unsigned(EA(3 downto 0)) ror to_integer(unsigned(EB)))) and "01111";  -- ROTAR A LA DERECHA
elsif (TIP_OPER="0111") then 
S<=(EA and EB);                               -- AND
elsif (TIP_OPER="1000") then 
S<=NOT(EA AND EB);                              -- NAND
elsif (TIP_OPER="1001") then 
S<=(EA or EB);                                -- OR
ELSE
S<="00000000";
END IF;
RES <= S;
end process;

end OPERACIONES;

--------------------------------------------------------------------------------------------------------------------------

Desplegar en la LCD

----------------------------------------------------------------------------------
-- LCD
----------------------------------------------------------------------------------
liBrAry IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity LCD is
    Port ( CLOCK, CLOCK_E, RESET : IN STD_LOGIC;
       INPUT1, INPUT2, OPER : STD_LOGIC_VECTOR(3 DOWNTO 0);
 S : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
       LC_E, LC_RS, LC_RW : OUT STD_LOGIC;
 LC_DB : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
end LCD;

Architecture IMPRIMIR of LCD is
-- SEÑALES DE LA LCD
SIGNAL E  : STD_LOGIC:= '0';
SIGNAL RS : STD_LOGIC:= '0';
SIGNAL RW : STD_LOGIC:= '0';
SIGNAL DB : STD_LOGIC_VECTOR(7 DOWNTO 0):= "00000000";

Begin

-- PANTALLA LCD
LC_E  <= E;
LC_RS <= RS;
LC_RW <= RW;
LC_DB <= DB;
PROCESS (RESET, CLOCK)
VARIABLE COUNTER  : INTEGER := 0;
VARIABLE AUX       : INTEGER := 0;
VARIABLE ACT_STEP    : INTEGER := 0;
VARIABLE NEXT_STEP : INTEGER := 0;
BEGIN
IF (RESET='1') THEN
COUNTER:=0;
ELSE
IF (RISING_EDGE(CLOCK) AND CLOCK_E='0') THEN
COUNTER := COUNTER + 1;
IF (COUNTER >= AUX) THEN
ACT_STEP := NEXT_STEP;
  NEXT_STEP := ACT_STEP + 1;
      CASE ACT_STEP IS
-- IniciAlizAcion 1
WHEN  0 => E <= '0'; 
AUX := 750000;
WHEN  1 => DB <= "00111111"; 
E <= '1'; AUX := 12;
WHEN  2 => E <= '0'; 
AUX := 205000;
WHEN  3 => DB <= "00111111"; 
E <= '1'; AUX := 12;
WHEN  4 => E <= '0'; 
AUX := 5000;
WHEN  5 => DB <= "00111111"; 
E <= '1'; AUX := 12;
WHEN  6 => E <= '0'; 
AUX := 2000;
WHEN  7 => DB <= "00101111"; 
E <= '1'; 
AUX := 12;
WHEN  8 => 
E <= '0'; 
AUX := 2000;
-- IniciAlizAcion 2
-- Function Set con DL 8 Bits
WHEN  9 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "00111111"; 
AUX := 12;
WHEN 10 => E <= '0'; 
AUX := 50;
WHEN 11 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10001111"; 
AUX := 12;
WHEN 12 => E <= '0'; 
AUX := 2000; 
-- ENTRY MODE
WHEN 13 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "00000110"; 
AUX := 12;
WHEN 14 => E <= '0';
AUX := 2000;
-- DisplAy On/Off
WHEN 15 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "00001100";  
AUX := 12;
WHEN 16 => E <= '0'; 
AUX := 2000; 
-- CleAr DisplAy
WHEN 17 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "00000001";  
AUX := 12;
WHEN 18 => E <= '0'; 
AUX := 82000;
-- EscriBir texto
-- Set DD RAM Address (0x02)
WHEN 19 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10000010";  
AUX := 12;
WHEN 20 => E <= '0'; 
AUX := 2000; 
-- EscriBir
WHEN 21 => E <= '1';
RS <= '1'; 
RW <= '0'; 
IF(INPUT1="0000") THEN
DB <= "00110000";  
ELSIF(INPUT1="0001") THEN
DB <="00110001";
ELSIF(INPUT1="0010") THEN
DB <="00110010";
ELSIF(INPUT1="0011") THEN
DB <="00110011";
ELSIF(INPUT1="0100") THEN
DB <="00110100";
ELSIF(INPUT1="0101") THEN
DB <="00110101";
ELSIF(INPUT1="0110") THEN
DB <="00110110";
ELSIF(INPUT1="0111") THEN
DB <="00110111";
ELSIF(INPUT1="1000") THEN
DB <="00111000";
ELSIF(INPUT1="1001") THEN
DB <="00111001";
ELSIF(INPUT1="1010" OR INPUT1="1011" OR INPUT1="1100" OR INPUT1="1101" OR INPUT1="1110" OR INPUT1="1111")THEN
DB <="00110001";
ELSE
DB <="00110000";
END IF;
AUX := 12;
WHEN 22 => E <= '0'; 
AUX := 2000;
-- Set DD RAM Address (0x03)
WHEN 23 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10000011";  
AUX := 12;
WHEN 24 => E <= '0'; 
AUX := 2000;
         WHEN 25 => E <= '1';
RS <= '1'; 
RW <= '0'; 
IF(INPUT1="1010") THEN
DB <="00110000";
ELSIF(INPUT1="1011") THEN
DB <="00110001";
ELSIF(INPUT1="1100") THEN
DB <="00110010";
ELSIF(INPUT1="1101") THEN
DB <="00110011";
ELSIF(INPUT1="1110") THEN
DB <="00110100";
ELSIF(INPUT1="1111") THEN
DB <="00110101";
ELSE
DB <="10100000";
END IF;
AUX := 12;
WHEN 26 => E <= '0'; 
AUX := 2000;
-- Set DD RAM Address (0x05)
WHEN 27 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10000101";  
AUX := 12;
WHEN 28 => E <= '0'; 
AUX := 2000;
         WHEN 29 => E <= '1';
RS <= '1'; 
RW <= '0'; 
IF(OPER="0000") THEN
DB <="00101011";  
ELSIF(OPER="0001") THEN
DB <="00101101";
ELSIF(OPER="0010") THEN
DB <="00101010";
ELSIF(OPER="0011") THEN
DB <="00101111";
ELSIF(OPER="0100") THEN
DB <="00100010";
ELSIF(OPER="0101") THEN
DB <="01111111";
ELSIF(OPER="0110") THEN
DB <="01111110";
ELSIF(OPER="0111") THEN
DB <="01100001";
ELSIF(OPER="1000") THEN
DB <="01101110";
ELSIF(OPER="1001") THEN
DB <="01101111";
ELSE
DB <="10100000";
END IF;
AUX := 12;
         WHEN 30 => E <= '0'; 
AUX := 2000;
         -- Set DD RAM Address (0x07)
WHEN 31 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10000111";  
AUX := 12;
WHEN 32 => E <= '0'; 
AUX := 2000;
         WHEN 33 => E <= '1';
RS <= '1'; 
RW <= '0'; 
IF(INPUT2="0000") THEN
DB <= "00110000";  
ELSIF(INPUT2="0001") THEN
DB <="00110001";
ELSIF(INPUT2="0010") THEN
DB <="00110010";
ELSIF(INPUT2="0011") THEN
DB <="00110011";
ELSIF(INPUT2="0100") THEN
DB <="00110100";
ELSIF(INPUT2="0101") THEN
DB <="00110101";
ELSIF(INPUT2="0110") THEN
DB <="00110110";
ELSIF(INPUT2="0111") THEN
DB <="00110111";
ELSIF(INPUT2="1000") THEN
DB <="00111000";
ELSIF(INPUT2="1001") THEN
DB <="00111001";
ELSIF(INPUT2="1010" OR INPUT2="1011" OR INPUT2="1100" OR INPUT2="1101" OR INPUT2="1110" OR INPUT2="1111")THEN
DB <="00110001";
ELSIF(OPER="0100")THEN
DB <="10100000";
ELSE
DB <="00110000";
END IF;
AUX := 12;
         WHEN 34 => E <= '0'; 
AUX := 2000;
-- Set DD RAM Address (0x08)
WHEN 35 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10001000";  
AUX := 12;
WHEN 36 => E <= '0'; 
AUX := 2000;
WHEN  37=> E <= '1';
RS <= '1'; 
RW <= '0'; 
IF(INPUT2="1010") THEN
DB <="00110000";
ELSIF(INPUT2="1011") THEN
DB <="00110001";
ELSIF(INPUT2="1100") THEN
DB <="00110010";
ELSIF(INPUT2="1101") THEN
DB <="00110011";
ELSIF(INPUT2="1110") THEN
DB <="00110100";
ELSIF(INPUT2="1111") THEN
DB <="00110101";
ELSE
DB <="10100000";
END IF;
AUX := 12;
WHEN 38 => E <= '0'; 
AUX := 2000;
-- Set DD RAM Address (0x10)
WHEN 39 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10001010";  
AUX := 12;
WHEN 40 => E <= '0'; 
AUX := 2000;
         WHEN 41 => E <= '1';
RS <= '1'; 
RW <= '0';
DB <="00111101";
AUX := 12;
WHEN 42 => E <= '0'; 
AUX := 2000;
-- Set DD RAM Address (0x12)
WHEN 43 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10001100";  
AUX := 12;
WHEN 44 => E <= '0'; 
AUX := 2000; 
         WHEN 45 => E<= '1';
         RS <= '1'; 
         RW <= '0';
  IF(S="00000000") THEN
DB <= "00110000";  
ELSIF(S="00000001" 
 OR S="00001010" 
 OR S="00001011" 
 OR S="00001100" 
 OR S="00001101" 
 OR S="00001110" 
 OR S="00001111"  
 OR S ="00001010" 
 OR S = "00001011"
 OR S = "00001100"
 OR S = "00001101"
 OR S = "00001110"
 OR S = "00001111"
 OR S = "00010000" 
 OR S = "00010001"
 OR S = "00010010"
 OR S = "00010011"
 OR S = "01100100"
 OR S = "01100101"
 OR S = "01100110"
 OR S = "01100111"
 OR S = "01101000"
 OR S = "01101001"
 OR S = "01101010"
 OR S = "01101011"
 OR S = "01101100"
 OR S = "01101101"
 OR S = "01101110"
 OR S = "01101111"
 OR S = "01110000"
 OR S = "01110001"
 OR S = "01110010"
 OR S = "01110011"
 OR S = "01110100"
 OR S = "01110101"
 OR S = "01110110"
 OR S = "01110111"
 OR S = "01111000"
 OR S = "01111001"
 OR S = "01111010"
 OR S = "01111011"
 OR S = "01111100"
 OR S = "01111101"
 OR S = "01111110"
 OR S = "01111111"
 OR S = "10000000"
 OR S = "10000001"
 OR S = "10000010"
 OR S = "10000011"
 OR S = "10000100"
 OR S = "10000101"
 OR S = "10000110"
 OR S = "10000111"
 OR S = "10001000"
 OR S = "10001001"
 OR S = "10001010"
 OR S = "10001011"
 OR S = "10001100"
 OR S = "10001101"
 OR S = "10001110"
 OR S = "10001111"
 OR S = "10010000"
 OR S = "10010001"
 OR S = "10010010"
 OR S = "10010011"
 OR S = "10010100"
 OR S = "10010101"
 OR S = "10010110"
 OR S = "10010111"
 OR S = "10011000"
 OR S = "10011001"
 OR S = "10011010"
 OR S = "10011011"
 OR S = "10011100"
 OR S = "10011101"
 OR S = "10011110"
 OR S = "10011111"
 OR S = "10100000"
 OR S = "10100001"
 OR S = "10100010"
 OR S = "10100011"
 OR S = "10100100"
 OR S = "10100101"
 OR S = "10100110"
 OR S = "10100111"
 OR S = "10101000"
 OR S = "10101001"
 OR S = "10101010"
 OR S = "10101011"
 OR S = "10101100"
 OR S = "10101101"
 OR S = "10101110"
 OR S = "10101111"
 OR S = "10110000"
 OR S = "10110001"
 OR S = "10110010"
 OR S = "10110011"
 OR S = "10110100"
 OR S = "10110101"
 OR S = "10110110"
 OR S = "10110111"
 OR S = "10111000"
 OR S = "10111001"
 OR S = "10111010"
 OR S = "10111011"
 OR S = "10111100"
 OR S = "10111101"
 OR S = "10111110"
 OR S = "10111111"
 OR S = "11000000"
 OR S = "11000001"
 OR S = "11000010"
 OR S = "11000011"
 OR S = "11000100"
 OR S = "11000101"
 OR S = "11000110"
 OR S = "11000111") THEN
DB <="00110001";
ELSIF(S="00000010"
 OR S = "00010100"
 OR S = "00010101"
 OR S = "00010110"
 OR S = "00010111"
 OR S = "00011000"
 OR S = "00011001"
 OR S = "00011010"
 OR S = "00011011"
 OR S = "00011100"
 OR S = "00011101" 
 OR S = "11001000"
 OR S = "11001001"
 OR S = "11001010"
 OR S = "11001011"
 OR S = "11001100"
 OR S = "11001101"
 OR S = "11001110"
 OR S = "11001111"
 OR S = "11010000"
 OR S = "11010001"
 OR S = "11010010"
 OR S = "11010011"
 OR S = "11010100"
 OR S = "11010101"
 OR S = "11010110"
 OR S = "11010111"
 OR S = "11011000"
 OR S = "11011001"
 OR S = "11011010"
 OR S = "11011011"
 OR S = "11011100"
 OR S = "11011101"
 OR S = "11011110"
 OR S = "11011111"
 OR S = "11100000"
 OR S = "11100001") THEN
DB <="00110010";
ELSIF(S="00000011"
 OR S = "00011110" 
 OR S = "00011111"
 OR S = "00100000" 
 OR S = "00100001"
 OR S = "00100010"
 OR S = "00100011"
 OR S = "00100100"
 OR S = "00100101"
 OR S = "00100110"
 OR S = "00100111") THEN
DB <="00110011";
ELSIF(S="00000100"
 OR S = "00101000" 
 OR S = "00101001"
 OR S = "00101010"
 OR S = "00101011"
 OR S = "00101100"
 OR S = "00101101"
 OR S = "00101110"
 OR S = "00101111"
 OR S = "00110000"
 OR S = "00110001") THEN
DB <="00110100";
ELSIF(S="00000101"
 OR S = "00110010" 
 OR S = "00110011"
 OR S = "00110100"
 OR S = "00110101"
 OR S = "00110110"
 OR S = "00110111"
 OR S = "00111000"
 OR S = "00111001"
 OR S = "00111010"
 OR S = "00111011") THEN
DB <="00110101";
ELSIF(S="00000110"
 OR S = "00111100"
 OR S = "00111101"
 OR S = "00111110"
 OR S = "00111111"
 OR S = "01000000"
 OR S = "01000001"
 OR S = "01000010"
 OR S = "01000011"
 OR S = "01000100"
 OR S = "01000101") THEN
DB <="00110110";
ELSIF(S="00000111"
 OR S = "00111100"
 OR S = "00111101"
 OR S = "00111110"
 OR S = "00111111"
 OR S = "01000000"
 OR S = "01000001"
 OR S = "01000010"
 OR S = "01000011"
 OR S = "01000100"
 OR S = "01000101") THEN
DB <="00110111";
ELSIF(S="00001000"
 OR S = "01010000"
 OR S = "01010001"
 OR S = "01010010"
 OR S = "01010011"
 OR S = "01010100"
 OR S = "01010101"
 OR S = "01010110"
 OR S = "01010111"
 OR S = "01011000"
 OR S = "01011001") THEN
DB <="00111000";
ELSIF(S="00001001"
 OR S = "01011010"
 OR S = "01011011"
 OR S = "01011100"
 OR S = "01011101"
 OR S = "01011110"
 OR S = "01011111"
 OR S = "01100000"
 OR S = "01100001"
 OR S = "01100010"
 OR S = "01100011") THEN
DB <="00111001";
ELSE
DB <="10100000";
END IF;
WHEN 46 => E <= '0'; 
AUX := 2000; 
-- Set DD RAM Address (0x13)
WHEN 47 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10001101";   
AUX := 12;
WHEN 48 => E <= '0'; 
AUX := 2000; 
         WHEN 49 => E<= '1';
         RS <= '1'; 
         RW <= '0';
  IF(  S = "00001010"
OR S = "00010100"
OR S = "00011110"
OR S = "00101000"
OR S = "00110010"
OR S = "00111100"
OR S = "01000110"
OR S = "01010000"
OR S = "01011010"
OR S = "01100100"
OR S = "01100101"
OR S = "01100110"
OR S = "01100111"
OR S = "01101000"
OR S = "01101001"
OR S = "01101010"
OR S = "01101011"
OR S = "01101100"
OR S = "01101101"
OR S = "11001000"
OR S = "11001001"
OR S = "11001010"
OR S = "11001011"
OR S = "11001100"
OR S = "11001101"
OR S = "11001110"
OR S = "11001111"
OR S = "11010000"
OR S = "11010001") THEN
DB <="00110000";
ELSIF( S = "00001011"
OR S = "00010101"
OR S = "00011111"
OR S = "00101001"
OR S = "00110011"
OR S = "00111101"
OR S = "01000111"
OR S = "01010001"
OR S = "01011011"
OR S = "01101110"
OR S = "01101111"
OR S = "01110000"
OR S = "01110001"
OR S = "01110010"
OR S = "01110011"
OR S = "01110100"
OR S = "01110101"
OR S = "01110110"
OR S = "01110111"
OR S = "11010010"
OR S = "11010011"
OR S = "11010100"
OR S = "11010101"
OR S = "11010110"
OR S = "11010111"
OR S = "11011000"
OR S = "11011001"
OR S = "11011010"
OR S = "11011011") THEN
DB <="00110001";
ELSIF( S = "00001100"
OR S = "00010110"
OR S = "00100000"
OR S = "00101010"
OR S = "00110100"
OR S = "00111110"
OR S = "01001000"
OR S = "01010010"
OR S = "01011100"
OR S = "01111000"
OR S = "01111001"
OR S = "01111010"
OR S = "01111011"
OR S = "01111100"
OR S = "01111101"
OR S = "01111110"
OR S = "01111111"
OR S = "10000000"
OR S = "10000001"
OR S = "11011100"
OR S = "11011101"
OR S = "11011110"
OR S = "11011111"
OR S = "11100000"
OR S = "11100001") THEN
DB <="00110010";
ELSIF( S = "00001101"
OR S = "00010111"
OR S = "00100001"
OR S = "00101011"
OR S = "00110101"
OR S = "00111111"
OR S = "01001001"
OR S = "01010011"
OR S = "01011101"
OR S = "10000010"
OR S = "10000011"
OR S = "10000100"
OR S = "10000101"
OR S = "10000110"
OR S = "10000111"
OR S = "10001000"
OR S = "10001001"
OR S = "10001010"
OR S = "10001011") THEN
DB <="00110011";
ELSIF( S = "00001110"
OR S = "00011000"
OR S = "00100010"
OR S = "00101100"
OR S = "00110110"
OR S = "01000000"
OR S = "01001010"
OR S = "01010100"
OR S = "01011110"
OR S = "10001100"
OR S = "10001101"
OR S = "10001110"
OR S = "10001111"
OR S = "10010000"
OR S = "10010001"
OR S = "10010010"
OR S = "10010011"
OR S = "10010100"
OR S = "10010101") THEN
DB <="00110100";
ELSIF( S = "00001111"
OR S = "00011001"
OR S = "00100011"
OR S = "00101101"
OR S = "00110111"
OR S = "01000001"
OR S = "01001011"
OR S = "01010101"
OR S = "01011111"
OR S = "10010110"
OR S = "10010111"
OR S = "10011000"
OR S = "10011001"
OR S = "10011010"
OR S = "10011011"
OR S = "10011100"
OR S = "10011101"
OR S = "10011110"
OR S = "10011111") THEN
DB <="00110101";
ELSIF( S = "00010000"
OR S = "00011010"
OR S = "00100100"
OR S = "00101110"
OR S = "00111000"
OR S = "01000010"
OR S = "01001100"
OR S = "01010110"
OR S = "01100000"
OR S = "10100000"
OR S = "10100001"
OR S = "10100010"
OR S = "10100011"
OR S = "10100100"
OR S = "10100101"
OR S = "10100110"
OR S = "10100111"
OR S = "10101000"
OR S = "10101001") THEN
DB <="00110110";
ELSIF( S = "00010001"
OR S = "00011011"
OR S = "00100101"
OR S = "00101111"
OR S = "00111001"
OR S = "01000011"
OR S = "01001101"
OR S = "01010111"
OR S = "01100001"
OR S = "10101010"
OR S = "10101011"
OR S = "10101100"
OR S = "10101101"
OR S = "10101110"
OR S = "10101111"
OR S = "10110000"
OR S = "10110001"
OR S = "10110010"
OR S = "10110011") THEN
DB <="00110111";
ELSIF( S = "00010010"
OR S = "00011100"
OR S = "00100110"
OR S = "00110000"
OR S = "00111010"
OR S = "01000100"
OR S = "01001110"
OR S = "01011000"
OR S = "01100010"
OR S = "10110100"
OR S = "10110101"
OR S = "10110110"
OR S = "10110111"
OR S = "10111000"
OR S = "10111001"
OR S = "10111010"
OR S = "10111011"
OR S = "10111100"
OR S = "10111101") THEN
DB <="00111000";
ELSIF( S = "00010011"
OR S = "00011101"
OR S = "00100111"
OR S = "00110001"
OR S = "00111011"
OR S = "01000101"
OR S = "01001111"
OR S = "01011001"
OR S = "01100011"
OR S = "10111110"
OR S = "10111111"
OR S = "11000000"
OR S = "11000001"
OR S = "11000010"
OR S = "11000011"
OR S = "11000100"
OR S = "11000101"
OR S = "11000110"
OR S = "11000111") THEN
DB <="00111001";
ELSE
DB <="10100000";
END IF;
WHEN 50 => E <= '0'; 
AUX := 2000; 
-- Set DD RAM Address (0x14)
WHEN 51 => E <= '1';
RS <= '0'; 
RW <= '0'; 
DB <= "10001110";  
AUX := 12;
WHEN 52 => E <= '0'; 
AUX := 2000; 
         WHEN 53 => E<= '1';
         RS <= '1'; 
         RW <= '0';
  IF( S = "01100100"
OR S = "01101110"
OR S = "01111000"
OR S = "10000010"
OR S = "10001100"
OR S = "10010110"
OR S = "10100000"
OR S = "10101010"
OR S = "10110100"
OR S = "10111110"
OR S = "11001000"
OR S = "11011100") THEN
DB <="00110000";
ELSIF( S = "01100101"
OR S = "01101111"
OR S = "01111001"
OR S = "10000011"
OR S = "10001101"
OR S = "10010111"
OR S = "10100001"
OR S = "10101011"
OR S = "10110101"
OR S = "10111111"
OR S = "11001001"
OR S = "11010011"
OR S = "11011101") THEN
DB <="00110001";
ELSIF( S = "01100110"
OR S = "01110000"
OR S = "01111010"
OR S = "10000100"
OR S = "10001110"
OR S = "10011000"
OR S = "10100010"
OR S = "10101100"
OR S = "10110110"
OR S = "11000000"
OR S = "11000001"
OR S = "11001010"
OR S = "11010100"
OR S = "11011110") THEN
DB <="00110010";
ELSIF( S = "01100111"
OR S = "01110001"
OR S = "01111011"
OR S = "10000101"
OR S = "10001111"
OR S = "10011001"
OR S = "10100011"
OR S = "10101101"
OR S = "10110111"
OR S = "11000001"
OR S = "11001011"
OR S = "11010101"
OR S = "11011111") THEN
DB <="00110011";
ELSIF( S = "01101000"
OR S = "01110010"
OR S = "01111100"
OR S = "10000110"
OR S = "10010000"
OR S = "10011010"
OR S = "10100100"
OR S = "10101110"
OR S = "10111000"
OR S = "11000010"
OR S = "11001100"
OR S = "11010110"
OR S = "11100000") THEN
DB <="00110100";
ELSIF( S = "01101001"
OR S = "01110011"
OR S = "01111101"
OR S = "10000111"
OR S = "10010001"
OR S = "10011011"
OR S = "10100101"
OR S = "10101111"
OR S = "10111001"
OR S = "11000011"
OR S = "11001101"
OR S = "11010111"
OR S = "11100001") THEN
DB <="00110101";
ELSIF( S = "01101010"
OR S = "01110100"
OR S = "01111110"
OR S = "10001000"
OR S = "10010010"
OR S = "10011100"
OR S = "10100110"
OR S = "10110000"
OR S = "10111010"
OR S = "11000100"
OR S = "11001110"
OR S = "11011000") THEN
DB <="00110110";
ELSIF( S = "01101011"
OR S = "01110101"
OR S = "01111111"
OR S = "10001001"
OR S = "10010011"
OR S = "10011101"
OR S = "10100111"
OR S = "10110001"
OR S = "10111011"
OR S = "11000101"
OR S = "11001111"
OR S = "11011001") THEN
DB <="00110111";
ELSIF(S = "01101100"
OR S = "01110110"
OR S = "10000000"
OR S = "10001010"
OR S = "10010100"
OR S = "10011110"
OR S = "10101000"
OR S = "10110010"
OR S = "10111100"
OR S = "11000110"
OR S = "11010000"
OR S = "11011010") THEN
DB <="00111000";
ELSIF( S = "01101101"
OR S = "01110111"
OR S = "10000001"
OR S = "10001011"
OR S = "10010101"
OR S = "10011111"
OR S = "10101001"
OR S = "10110011"
OR S = "10111101"
OR S = "11000111"
OR S = "11010001"
OR S = "11010010"
OR S = "11011011") THEN
DB <="00111001";
ELSE
DB <="10100000";
END IF;
WHEN 54 => E <= '0'; 
AUX := 2000;
WHEN OTHERS => NEXT_STEP := 19; AUX := 0;
 END CASE;
      COUNTER := 0;  
END IF;
END IF;
END IF;
END PROCESS;
end IMPRIMIR;


--------------------------------------------------------------------------------------------------------------------------

Lectura de puerto PS2 (VERSIÓN DE PRUEBA)

- DECODIFICADOR

----------------------------------------------------------------------------------
-- DECODIFICADOR
----------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY DECODER IS
  GENERIC(
      clk_freq                  : INTEGER := 50_000_000; --system clock frequency in Hz
      ps2_debounce_counter_size : INTEGER := 8);         --set such that 2^size/clk_freq = 5us (size = 8 for 50MHz)
  PORT(
      CLK        : IN  STD_LOGIC;                     --system clock input
      ps2_clk    : IN  STD_LOGIC;                     --clock signal from PS2 keyboard
      ps2_data   : IN  STD_LOGIC;                     --data signal from PS2 keyboard
OUT1       : BUFFER STD_LOGIC_VECTOR(3 DOWNTO 0);
OUT2       : BUFFER STD_LOGIC_VECTOR(3 DOWNTO 0));
END DECODER;

ARCHITECTURE CODIFICACION OF DECODER IS
  TYPE STATES IS(S0, S1, S2, S3, S4, S5);
  SIGNAL ED_ACT, ED_SIG    : STATES;
  TYPE machine IS(ready, new_code, translate, output);              --needed states
  SIGNAL state             : machine;                               --state machine
  SIGNAL ps2_code_new      : STD_LOGIC;                             --new PS2 code flag from ps2_keyboard component
  SIGNAL ps2_code          : STD_LOGIC_VECTOR(7 DOWNTO 0);          --PS2 code input form ps2_keyboard component
  SIGNAL prev_ps2_code_new : STD_LOGIC := '1';                      --value of ps2_code_new flag on previous clock
  SIGNAL break             : STD_LOGIC := '0';                      --'1' for break code, '0' for make code
  SIGNAL e0_code           : STD_LOGIC := '0';                      --'1' for multi-code commands, '0' for single code commands
  SIGNAL caps_lock         : STD_LOGIC := '0';                      --'1' if caps lock is active, '0' if caps lock is inactive
  SIGNAL control_r         : STD_LOGIC := '0';                      --'1' if right control key is held down, else '0'
  SIGNAL control_l         : STD_LOGIC := '0';                      --'1' if left control key is held down, else '0'
  SIGNAL shift_r           : STD_LOGIC := '0';                      --'1' if right shift is held down, else '0'
  SIGNAL shift_l           : STD_LOGIC := '0';                      --'1' if left shift is held down, else '0'
  SIGNAL ascii             : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"FF"; --internal value of ASCII translation
  SIGNAL ascii_new         : STD_LOGIC;                     --output flag indicating new ASCII value
  SIGNAL ascii_code        : STD_LOGIC_VECTOR(6 DOWNTO 0); --ASCII value
  SIGNAL BIN               : STD_LOGIC_VECTOR(7 DOWNTO 0);
  SIGNAL BINREG            : STD_LOGIC_VECTOR(7 DOWNTO 0);

  --declare PS2 keyboard interface component
  COMPONENT ps2_keyboard IS
    GENERIC(
      clk_freq              : INTEGER;  --system clock frequency in Hz
      debounce_counter_size : INTEGER); --set such that 2^size/clk_freq = 5us (size = 8 for 50MHz)
    PORT(
      clk          : IN  STD_LOGIC;                     --system clock
      ps2_clk      : IN  STD_LOGIC;                     --clock signal from PS2 keyboard
      ps2_data     : IN  STD_LOGIC;                     --data signal from PS2 keyboard
      ps2_code_new : OUT STD_LOGIC;                     --flag that new PS/2 code is available on ps2_code bus
      ps2_code     : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --code received from PS/2
  END COMPONENT;

BEGIN

  --instantiate PS2 keyboard interface logic
  ps2_keyboard_0:  ps2_keyboard
    GENERIC MAP(clk_freq => clk_freq, debounce_counter_size => ps2_debounce_counter_size)
    PORT MAP(clk => clk, ps2_clk => ps2_clk, ps2_data => ps2_data, ps2_code_new => ps2_code_new, ps2_code => ps2_code);

  PROCESS(clk)
  BEGIN
    IF(clk'EVENT AND clk = '1') THEN
      prev_ps2_code_new <= ps2_code_new; --keep track of previous ps2_code_new values to determine low-to-high transitions
      CASE state IS
     
        --ready state: wait for a new PS2 code to be received
        WHEN ready =>
          IF(prev_ps2_code_new = '0' AND ps2_code_new = '1') THEN --new PS2 code received
            ascii_new <= '0';                                       --reset new ASCII code indicator
            state <= new_code;                                      --proceed to new_code state
          ELSE                                                    --no new PS2 code received yet
            state <= ready;                                         --remain in ready state
          END IF;
         
        --new_code state: determine what to do with the new PS2 code
        WHEN new_code =>
          IF(ps2_code = x"F0") THEN    --code indicates that next command is break
            break <= '1';                --set break flag
            state <= ready;              --return to ready state to await next PS2 code
          ELSIF(ps2_code = x"E0") THEN --code indicates multi-key command
            e0_code <= '1';              --set multi-code command flag
            state <= ready;              --return to ready state to await next PS2 code
          ELSE                         --code is the last PS2 code in the make/break code
            ascii(7) <= '1';             --set internal ascii value to unsupported code (for verification)
            state <= translate;          --proceed to translate state
          END IF;

        --translate state: translate PS2 code to ASCII value
        WHEN translate =>
            break <= '0';    --reset break flag
            e0_code <= '0';  --reset multi-code command flag
           
            --handle codes for control, shift, and caps lock
            CASE ps2_code IS
              WHEN x"58" =>                   --caps lock code
                IF(break = '0') THEN            --if make command
                  caps_lock <= NOT caps_lock;     --toggle caps lock
                END IF;
              WHEN x"14" =>                   --code for the control keys
                IF(e0_code = '1') THEN          --code for right control
                  control_r <= NOT break;         --update right control flag
                ELSE                            --code for left control
                  control_l <= NOT break;         --update left control flag
                END IF;
              WHEN x"12" =>                   --left shift code
                shift_l <= NOT break;           --update left shift flag
              WHEN x"59" =>                   --right shift code
                shift_r <= NOT break;           --update right shift flag
              WHEN OTHERS => NULL;
            END CASE;
       
            --translate control codes (these do not depend on shift or caps lock)
            IF(control_l = '1' OR control_r = '1') THEN
              CASE ps2_code IS
                WHEN x"1E" => ascii <= x"00"; BIN <= "00011110"; --^@  NUL
                WHEN x"1C" => ascii <= x"01"; BIN <= "00011100"; --^A  SOH
                WHEN x"32" => ascii <= x"02"; BIN <= "00110010"; --^B  STX
                WHEN x"21" => ascii <= x"03"; BIN <= "00100001"; --^C  ETX
                WHEN x"23" => ascii <= x"04"; BIN <= "00100011"; --^D  EOT
                WHEN x"24" => ascii <= x"05"; BIN <= "00100100"; --^E  ENQ
                WHEN x"2B" => ascii <= x"06"; BIN <= "00101011"; --^F  ACK
                WHEN x"34" => ascii <= x"07"; BIN <= "00110100"; --^G  BEL
                WHEN x"33" => ascii <= x"08"; BIN <= "00110011"; --^H  BS
                WHEN x"43" => ascii <= x"09"; BIN <= "01000011"; --^I  HT
                WHEN x"3B" => ascii <= x"0A"; BIN <= "00111011"; --^J  LF
                WHEN x"42" => ascii <= x"0B"; BIN <= "01000010"; --^K  VT
                WHEN x"4B" => ascii <= x"0C"; BIN <= "01001011"; --^L  FF
                WHEN x"3A" => ascii <= x"0D"; BIN <= "00111010"; --^M  CR
                WHEN x"31" => ascii <= x"0E"; BIN <= "00110001"; --^N  SO
                WHEN x"44" => ascii <= x"0F"; BIN <= "01000100"; --^O  SI
                WHEN x"4D" => ascii <= x"10"; BIN <= "01001101"; --^P  DLE
                WHEN x"15" => ascii <= x"11"; BIN <= "00010101"; --^Q  DC1
                WHEN x"2D" => ascii <= x"12"; BIN <= "00101101"; --^R  DC2
                WHEN x"1B" => ascii <= x"13"; BIN <= "00011011"; --^S  DC3
                WHEN x"2C" => ascii <= x"14"; BIN <= "00101100"; --^T  DC4
                WHEN x"3C" => ascii <= x"15"; BIN <= "00111100"; --^U  NAK
                WHEN x"2A" => ascii <= x"16"; BIN <= "00101010"; --^V  SYN
                WHEN x"1D" => ascii <= x"17"; BIN <= "00011101"; --^W  ETB
                WHEN x"22" => ascii <= x"18"; BIN <= "00100010"; --^X  CAN
                WHEN x"35" => ascii <= x"19"; BIN <= "00110101"; --^Y  EM
                WHEN x"1A" => ascii <= x"1A"; BIN <= "00011010"; --^Z  SUB
                WHEN x"54" => ascii <= x"1B"; BIN <= "01010100"; --^[  ESC
                WHEN x"5D" => ascii <= x"1C"; BIN <= "01011101"; --^\  FS
                WHEN x"5B" => ascii <= x"1D"; BIN <= "01011011"; --^]  GS
                WHEN x"36" => ascii <= x"1E"; BIN <= "00110110"; --^^  RS
                WHEN x"4E" => ascii <= x"1F"; BIN <= "01001110"; --^_  US
                WHEN x"4A" => ascii <= x"7F"; BIN <= "01001010"; --^?  DEL
                WHEN OTHERS => NULL;
              END CASE;
            ELSE --if control keys are not pressed
           
              --translate characters that do not depend on shift, or caps lock
              CASE ps2_code IS
                WHEN x"29" => ascii <= x"20"; BIN <= "00101001"; --space
                WHEN x"66" => ascii <= x"08"; BIN <= "01100110"; --backspace (BS control code)
                WHEN x"0D" => ascii <= x"09"; BIN <= "00001101"; --tab (HT control code)
                WHEN x"5A" => ascii <= x"0D"; BIN <= "01011010"; --enter (CR control code)
                WHEN x"76" => ascii <= x"1B"; BIN <= "01110110"; --escape (ESC control code)
                WHEN x"71" =>
                  IF(e0_code = '1') THEN      --ps2 code for delete is a multi-key code
                    ascii <= x"7F"; BIN <= "01111111";           --delete
                  END IF;
                WHEN OTHERS => NULL;
              END CASE;
             
              --translate letters (these depend on both shift and caps lock)
              IF((shift_r = '0' AND shift_l = '0' AND caps_lock = '0') OR
                ((shift_r = '1' OR shift_l = '1') AND caps_lock = '1')) THEN  --letter is lowercase
                CASE ps2_code IS            
                  WHEN x"1C" => ascii <= x"61"; BIN <= "00011100"; --a
                  WHEN x"32" => ascii <= x"62"; BIN <= "00110010"; --b
                  WHEN x"21" => ascii <= x"63"; BIN <= "00100001"; --c
                  WHEN x"23" => ascii <= x"64"; BIN <= "00100011"; --d
                  WHEN x"24" => ascii <= x"65"; BIN <= "00100100"; --e
                  WHEN x"2B" => ascii <= x"66"; BIN <= "00101011"; --f
                  WHEN x"34" => ascii <= x"67"; BIN <= "00110100"; --g
                  WHEN x"33" => ascii <= x"68"; BIN <= "00110011"; --h
                  WHEN x"43" => ascii <= x"69"; BIN <= "01000011"; --i
                  WHEN x"3B" => ascii <= x"6A"; BIN <= "00111011"; --j
                  WHEN x"42" => ascii <= x"6B"; BIN <= "01000010"; --k
                  WHEN x"4B" => ascii <= x"6C"; BIN <= "01001011"; --l
                  WHEN x"3A" => ascii <= x"6D"; BIN <= "00111010"; --m
                  WHEN x"31" => ascii <= x"6E"; BIN <= "00110001"; --n
                  WHEN x"44" => ascii <= x"6F"; BIN <= "01000100"; --o
                  WHEN x"4D" => ascii <= x"70"; BIN <= "01001101"; --p
                  WHEN x"15" => ascii <= x"71"; BIN <= "00010101"; --q
                  WHEN x"2D" => ascii <= x"72"; BIN <= "00101101"; --r
                  WHEN x"1B" => ascii <= x"73"; BIN <= "00011011"; --s
                  WHEN x"2C" => ascii <= x"74"; BIN <= "00101100"; --t
                  WHEN x"3C" => ascii <= x"75"; BIN <= "00111100"; --u
                  WHEN x"2A" => ascii <= x"76"; BIN <= "00101010"; --v
                  WHEN x"1D" => ascii <= x"77"; BIN <= "00011101"; --w
                  WHEN x"22" => ascii <= x"78"; BIN <= "00100010"; --x
                  WHEN x"35" => ascii <= x"79"; BIN <= "00110101"; --y
                  WHEN x"1A" => ascii <= x"7A"; BIN <= "00011010"; --z
                  WHEN OTHERS => NULL;
                END CASE;
              ELSE                                     --letter is uppercase
                CASE ps2_code IS          
                  WHEN x"1C" => ascii <= x"41"; BIN <= "00011100"; --A
                  WHEN x"32" => ascii <= x"42"; BIN <= "00110010"; --B
                  WHEN x"21" => ascii <= x"43"; BIN <= "00100001"; --C
                  WHEN x"23" => ascii <= x"44"; BIN <= "00100011"; --D
                  WHEN x"24" => ascii <= x"45"; BIN <= "00100100"; --E
                  WHEN x"2B" => ascii <= x"46"; BIN <= "00101011"; --F
                  WHEN x"34" => ascii <= x"47"; BIN <= "00110100"; --G
                  WHEN x"33" => ascii <= x"48"; BIN <= "00110011"; --H
                  WHEN x"43" => ascii <= x"49"; BIN <= "01000011"; --I
                  WHEN x"3B" => ascii <= x"4A"; BIN <= "00111011"; --J
                  WHEN x"42" => ascii <= x"4B"; BIN <= "01000010"; --K
                  WHEN x"4B" => ascii <= x"4C"; BIN <= "01001011"; --L
                  WHEN x"3A" => ascii <= x"4D"; BIN <= "00111010"; --M
                  WHEN x"31" => ascii <= x"4E"; BIN <= "00110001"; --N
                  WHEN x"44" => ascii <= x"4F"; BIN <= "01000100"; --O
                  WHEN x"4D" => ascii <= x"50"; BIN <= "01001101"; --P
                  WHEN x"15" => ascii <= x"51"; BIN <= "00010101"; --Q
                  WHEN x"2D" => ascii <= x"52"; BIN <= "00101101"; --R
                  WHEN x"1B" => ascii <= x"53"; BIN <= "00011011"; --S
                  WHEN x"2C" => ascii <= x"54"; BIN <= "00101100"; --T
                  WHEN x"3C" => ascii <= x"55"; BIN <= "00111100"; --U
                  WHEN x"2A" => ascii <= x"56"; BIN <= "00101010"; --V
                  WHEN x"1D" => ascii <= x"57"; BIN <= "00011101"; --W
                  WHEN x"22" => ascii <= x"58"; BIN <= "00100010"; --X
                  WHEN x"35" => ascii <= x"59"; BIN <= "00110101"; --Y
                  WHEN x"1A" => ascii <= x"5A"; BIN <= "00011010"; --Z
                  WHEN OTHERS => NULL;
                END CASE;
              END IF;
             
              --translate numbers and symbols (these depend on shift but not caps lock)
              IF(shift_l = '1' OR shift_r = '1') THEN  --key's secondary character is desired
                CASE ps2_code IS            
                  WHEN x"16" => ascii <= x"21"; BIN <= "00010110"; --!
                  WHEN x"52" => ascii <= x"22"; BIN <= "01010010"; --"
                  WHEN x"26" => ascii <= x"23"; BIN <= "00100110"; --#
                  WHEN x"25" => ascii <= x"24"; BIN <= "00100101"; --$
                  WHEN x"2E" => ascii <= x"25"; BIN <= "00101110"; --%
                  WHEN x"3D" => ascii <= x"26"; BIN <= "00111101"; --&            
                  WHEN x"46" => ascii <= x"28"; BIN <= "01000110"; --(
                  WHEN x"45" => ascii <= x"29"; BIN <= "01000101"; --)
                  WHEN x"3E" => ascii <= x"2A"; BIN <= "00111110"; --*
                  WHEN x"55" => ascii <= x"2B"; BIN <= "01010101"; --+
                  WHEN x"4C" => ascii <= x"3A"; BIN <= "01001100"; --:
                  WHEN x"41" => ascii <= x"3C"; BIN <= "01000001"; --<
                  WHEN x"49" => ascii <= x"3E"; BIN <= "01001001"; -->
                  WHEN x"4A" => ascii <= x"3F"; BIN <= "01001010"; --?
                  WHEN x"1E" => ascii <= x"40"; BIN <= "00011110"; --@
                  WHEN x"36" => ascii <= x"5E"; BIN <= "00110110"; --^
                  WHEN x"4E" => ascii <= x"5F"; BIN <= "01001110"; --_
                  WHEN x"54" => ascii <= x"7B"; BIN <= "01010100"; --{
                  WHEN x"5D" => ascii <= x"7C"; BIN <= "01011101"; --|
                  WHEN x"5B" => ascii <= x"7D"; BIN <= "01011011"; --}
                  WHEN x"0E" => ascii <= x"7E"; BIN <= "00001110"; --~
                  WHEN OTHERS => NULL;
                END CASE;
              ELSE                                     --key's primary character is desired
                CASE ps2_code IS
                  WHEN x"45" => ascii <= x"30"; BIN <= "00000000"; --0
                  WHEN x"16" => ascii <= x"31"; BIN <= "00000001"; --1
                  WHEN x"1E" => ascii <= x"32"; BIN <= "00000010"; --2
                  WHEN x"26" => ascii <= x"33"; BIN <= "00000011"; --3
                  WHEN x"25" => ascii <= x"34"; BIN <= "00000100"; --4
                  WHEN x"2E" => ascii <= x"35"; BIN <= "00000101"; --5
                  WHEN x"36" => ascii <= x"36"; BIN <= "00000110"; --6
                  WHEN x"3D" => ascii <= x"37"; BIN <= "00000111"; --7
                  WHEN x"3E" => ascii <= x"38"; BIN <= "00001000"; --8
                  WHEN x"46" => ascii <= x"39"; BIN <= "00001001"; --9
                  WHEN x"52" => ascii <= x"27"; BIN <= "01010010"; --'
                  WHEN x"41" => ascii <= x"2C"; BIN <= "01000001"; --,
                  WHEN x"4E" => ascii <= x"2D"; BIN <= "01001110"; ---
                  WHEN x"49" => ascii <= x"2E"; BIN <= "01001001"; --.
                  WHEN x"4A" => ascii <= x"2F"; BIN <= "01001010"; --/
                  WHEN x"4C" => ascii <= x"3B"; BIN <= "01001100"; --;
                  WHEN x"55" => ascii <= x"3D"; BIN <= "01010101"; --=
                  WHEN x"54" => ascii <= x"5B"; BIN <= "01010100"; --[
                  WHEN x"5D" => ascii <= x"5C"; BIN <= "01011101"; --\
                  WHEN x"5B" => ascii <= x"5D"; BIN <= "01011011"; --]
                  WHEN x"0E" => ascii <= x"60"; BIN <= "00001110"; --`
                  WHEN OTHERS => NULL;
                END CASE;
              END IF;
             
            END IF;
         
          IF(break = '0') THEN  --the code is a make
            state <= output;      --proceed to output state
          ELSE                  --code is a break
            state <= ready;       --return to ready state to await next PS2 code
          END IF;
       
        --output state: verify the code is valid and output the ASCII value
        WHEN output =>
          IF(ascii(7) = '0') THEN            --the PS2 code has an ASCII output
            ascii_new <= '1';                  --set flag indicating new ASCII output
            ascii_code <= ascii(6 DOWNTO 0);   --output the ASCII value
BINREG<=BIN;
          END IF;
          state <= ready;                    --return to ready state to await next PS2 code
          BIN <= "00000000";
      END CASE;
    END IF;
  END PROCESS;
 
PROCESS (BIN, BINREG)
BEGIN

IF(BINREG /= BIN)THEN
ED_ACT<=ED_SIG;
 
  CASE ED_ACT IS
  WHEN S0 =>
  OUT1 <= "0000";
  OUT2 <= "0000";
  IF (BIN > "00000000") THEN
  ED_SIG <= S1;
  ELSIF(BIN="01011010")THEN
  ED_SIG<=S3;
  ELSE
  ED_SIG<=S0;
  END IF;
 
  WHEN S1 =>
  OUT2<="0000";
  IF(BIN="00000000")THEN
  OUT1<="0000";
  ELSIF(BIN="00000001")THEN
  OUT1<="0001";
  ELSIF(BIN="00000010")THEN
  OUT1<="0010";
  ELSIF(BIN="00000011")THEN
  OUT1<="0011";
  ELSIF(BIN="00000100")THEN
  OUT1<="0100";
  ELSIF(BIN="00000101")THEN
  OUT1<="0101";
  ELSIF(BIN="00000110")THEN
  OUT1<="0110";
  ELSIF(BIN="00000111")THEN
  OUT1<="0111";
  ELSIF(BIN="00001000")THEN
  OUT1<="1000";
  ELSIF(BIN="00001001")THEN
  OUT1<="1001";
  ELSIF(BIN="01011010")THEN
  ED_SIG<=S3;
  ELSE
  OUT1<=OUT1;
  ED_SIG<=S1;
  END IF;
  IF(OUT1="0001")THEN
  ED_SIG<=S2;
  ELSE
  ED_SIG<=S3;
  END IF;
 
  WHEN S2 =>
  OUT2<="0000";
  IF(BIN="00000000")THEN
  OUT1<="1010";
  ELSIF(BIN="00000001")THEN
  OUT1<="1011";
  ELSIF(BIN="00000010")THEN
  OUT1<="1100";
  ELSIF(BIN="00000011")THEN
  OUT1<="1101";
  ELSIF(BIN="00000100")THEN
  OUT1<="1110";
  ELSIF(BIN="00000101")THEN
  OUT1<="1111";
  ELSIF(BIN="01011010")THEN
  ED_SIG<=S3;
  ELSE
  OUT1<=OUT1;
  ED_SIG<=S2;
  END IF;
 
  WHEN S3 =>
  OUT1<=OUT1;
  IF(BIN="00000000")THEN
  OUT2<="0000";
  ELSIF(BIN="00000001")THEN
  OUT2<="0001";
  ELSIF(BIN="00000010")THEN
  OUT2<="0010";
  ELSIF(BIN="00000011")THEN
  OUT2<="0011";
  ELSIF(BIN="00000100")THEN
  OUT2<="0100";
  ELSIF(BIN="00000101")THEN
  OUT2<="0101";
  ELSIF(BIN="00000110")THEN
  OUT2<="0110";
  ELSIF(BIN="00000111")THEN
  OUT2<="0111";
  ELSIF(BIN="00001000")THEN
  OUT2<="1000";
  ELSIF(BIN="00001001")THEN
  OUT2<="1001";
  ELSIF(BIN="01011010")THEN
  ED_SIG<=S5;
  ELSE
  OUT2<=OUT2;
  ED_SIG<=S3;
  END IF;
  IF(OUT2="0001")THEN
  ED_SIG<=S4;
  ELSE
  ED_SIG<=S5;
  END IF;
 
  WHEN S4 =>
  OUT2<=OUT1;
  IF(BIN="00000000")THEN
  OUT2<="1010";
  ELSIF(BIN="00000001")THEN
  OUT2<="1011";
  ELSIF(BIN="00000010")THEN
  OUT2<="1100";
  ELSIF(BIN="00000011")THEN
  OUT2<="1101";
  ELSIF(BIN="00000100")THEN
  OUT2<="1110";
  ELSIF(BIN="00000101")THEN
  OUT2<="1111";
  ELSIF(BIN="01011010")THEN
  ED_SIG<=S5;
  ELSE
  OUT2<=OUT2;
  ED_SIG<=S4;
  END IF;
 
  WHEN S5 =>
  OUT1<=OUT1;
  OUT2<=OUT2;
  IF(BIN="01011010")THEN
  ED_SIG<=S0;
  END IF;
 
  END CASE;
 
  END IF;
END PROCESS;

END CODIFICACION;

--------------------------------------------------------------------------------------------------------------------------


- LECTURA DEL TECLADO

----------------------------------------------------------------------------------
-- TECLADO
----------------------------------------------------------------------------------
librAry IEEE;
use IEEE.STD_LOGIC_1164.ALL;


LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY ps2_keyboard IS
  GENERIC(
    clk_freq              : INTEGER := 50_000_000; --system clock frequency in Hz
    debounce_counter_size : INTEGER := 8);         --set such that (2^size)/clk_freq = 5us (size = 8 for 50MHz)
  PORT(
    clk          : IN  STD_LOGIC;                     --system clock
    ps2_clk      : IN  STD_LOGIC;                     --clock signal from PS/2 keyboard
    ps2_data     : IN  STD_LOGIC;                     --data signal from PS/2 keyboard
    ps2_code_new : OUT STD_LOGIC;                     --flag that new PS/2 code is available on ps2_code bus
    ps2_code     : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --code received from PS/2
END ps2_keyboard;

ARCHITECTURE logic OF ps2_keyboard IS
  SIGNAL sync_ffs     : STD_LOGIC_VECTOR(1 DOWNTO 0);       --synchronizer flip-flops for PS/2 signals
  SIGNAL ps2_clk_int  : STD_LOGIC;                          --debounced clock signal from PS/2 keyboard
  SIGNAL ps2_data_int : STD_LOGIC;                          --debounced data signal from PS/2 keyboard
  SIGNAL ps2_word     : STD_LOGIC_VECTOR(10 DOWNTO 0);      --stores the ps2 data word
  SIGNAL error        : STD_LOGIC;                          --validate parity, start, and stop bits
  SIGNAL count_idle   : INTEGER RANGE 0 TO clk_freq/18_000; --counter to determine PS/2 is idle
 
  --declare debounce component for debouncing PS2 input signals
  COMPONENT debounce IS
    GENERIC(
      counter_size : INTEGER); --debounce period (in seconds) = 2^counter_size/(clk freq in Hz)
    PORT(
      clk    : IN  STD_LOGIC;  --input clock
      button : IN  STD_LOGIC;  --input signal to be debounced
      result : OUT STD_LOGIC); --debounced signal
  END COMPONENT;
BEGIN

  --synchronizer flip-flops
  PROCESS(clk)
  BEGIN
    IF(clk'EVENT AND clk = '1') THEN  --rising edge of system clock
      sync_ffs(0) <= ps2_clk;           --synchronize PS/2 clock signal
      sync_ffs(1) <= ps2_data;          --synchronize PS/2 data signal
    END IF;
  END PROCESS;

  --debounce PS2 input signals
  debounce_ps2_clk: debounce
    GENERIC MAP(counter_size => debounce_counter_size)
    PORT MAP(clk => clk, button => sync_ffs(0), result => ps2_clk_int);
  debounce_ps2_data: debounce
    GENERIC MAP(counter_size => debounce_counter_size)
    PORT MAP(clk => clk, button => sync_ffs(1), result => ps2_data_int);

  --input PS2 data
  PROCESS(ps2_clk_int)
  BEGIN
    IF(ps2_clk_int'EVENT AND ps2_clk_int = '0') THEN    --falling edge of PS2 clock
      ps2_word <= ps2_data_int & ps2_word(10 DOWNTO 1);   --shift in PS2 data bit
    END IF;
  END PROCESS;
   
  --verify that parity, start, and stop bits are all correct
  error <= NOT (NOT ps2_word(0) AND ps2_word(10) AND (ps2_word(9) XOR ps2_word(8) XOR
        ps2_word(7) XOR ps2_word(6) XOR ps2_word(5) XOR ps2_word(4) XOR ps2_word(3) XOR
        ps2_word(2) XOR ps2_word(1)));

  --determine if PS2 port is idle (i.e. last transaction is finished) and output result
  PROCESS(clk)
  BEGIN
    IF(clk'EVENT AND clk = '1') THEN           --rising edge of system clock
   
      IF(ps2_clk_int = '0') THEN                 --low PS2 clock, PS/2 is active
        count_idle <= 0;                           --reset idle counter
      ELSIF(count_idle /= clk_freq/18_000) THEN  --PS2 clock has been high less than a half clock period (<55us)
          count_idle <= count_idle + 1;            --continue counting
      END IF;
     
      IF(count_idle = clk_freq/18_000 AND error = '0') THEN  --idle threshold reached and no errors detected
        ps2_code_new <= '1';                                   --set flag that new PS/2 code is available
        ps2_code <= ps2_word(8 DOWNTO 1);                      --output new PS/2 code
      ELSE                                                   --PS/2 port active or error detected
        ps2_code_new <= '0';                                   --set flag that PS/2 transaction is in progress
      END IF;
     
    END IF;
  END PROCESS;
 
END logic;

--------------------------------------------------------------------------------------------------------------------------


- CÓDIGO DE COMPONENTE ANTIRREBOTE

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY debounce IS
  GENERIC(
    counter_size  :  INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
  PORT(
    clk     : IN  STD_LOGIC;  --input clock
    button  : IN  STD_LOGIC;  --input signal to be debounced
    result  : OUT STD_LOGIC); --debounced signal
END debounce;

ARCHITECTURE logic OF debounce IS
  SIGNAL flipflops   : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
  SIGNAL counter_set : STD_LOGIC;                    --sync reset to zero
  SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
BEGIN

  counter_set <= flipflops(0) xor flipflops(1);   --determine when to start/reset counter
  
  PROCESS(clk)
  BEGIN
    IF(clk'EVENT and clk = '1') THEN
      flipflops(0) <= button;
      flipflops(1) <= flipflops(0);
      If(counter_set = '1') THEN                  --reset counter because input is changing
        counter_out <= (OTHERS => '0');
      ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
        counter_out <= counter_out + 1;
      ELSE                                        --stable input time is met
        result <= flipflops(1);
      END IF;    
    END IF;
  END PROCESS;
END logic;

--------------------------------------------------------------------------------------------------------------------------


FUENTE DE CODIGO DE TECLADO, ANTIRREBOTE Y PARTE DEL DECODIFICADOR

https://eewiki.net/pages/viewpage.action?pageId=28278929