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;
-- 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;
----------------------------------------------------------------------------------
-- 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
No hay comentarios:
Publicar un comentario