--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- FileName: kbd.vhd
|
-- FileName: kbd.vhd
|
-- Dependencies: debounce.vhd
|
-- Dependencies: debounce.vhd
|
-- Design Software: Quartus II 32-bit Version 12.1 Build 177 SJ Full Version
|
-- Design Software: Quartus II 32-bit Version 12.1 Build 177 SJ Full Version
|
--
|
--
|
-- HDL CODE is PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
-- HDL CODE is PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
--
|
--
|
-- Version History
|
-- Version History
|
-- Version 1.0 11/29/2013 Scott Larson
|
-- Version 1.0 11/29/2013 Scott Larson
|
-- Initial Public Release
|
-- Initial Public Release
|
--
|
--
|
-- See https://eewiki.net/pages/viewpage.action?pageId=28279002
|
-- See https://eewiki.net/pages/viewpage.action?pageId=28279002
|
--
|
--
|
-- @note This file has been renamed and updated from the original.
|
-- @note This file has been renamed and updated from the original.
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
|
use work.util.common_generics;
|
|
|
package kbd_pkg is
|
package kbd_pkg is
|
|
|
component ps2_kbd_top is
|
component ps2_kbd_top is
|
generic(
|
generic(
|
clock_frequency: integer := 50000000; -- system clock frequency in hz
|
clock_frequency: integer := 50000000; -- system clock frequency in Hz
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50MHz)
|
port(
|
port(
|
clk: in std_ulogic; -- system clock input
|
clk: in std_ulogic; -- system clock input
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
ascii_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
ascii_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
end component;
|
end component;
|
|
|
component ps2_kbd_core is
|
component ps2_kbd_core is
|
generic(
|
generic(
|
clock_frequency: integer := 50000000; -- system clock frequency in hz
|
clock_frequency: integer := 50000000; -- system clock frequency in Hz
|
debounce_counter_size: integer := 8); -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50mhz)
|
debounce_counter_size: integer := 8); -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50MHz)
|
port(
|
port(
|
clk: in std_ulogic; -- system clock
|
clk: in std_ulogic; -- system clock
|
ps2_clk: in std_ulogic; -- clock signal from PS/2 keyboard
|
ps2_clk: in std_ulogic; -- clock signal from PS/2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS/2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS/2 keyboard
|
ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus
|
ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus
|
ps2_code: out std_ulogic_vector(7 downto 0)); -- code received from PS/2
|
ps2_code: out std_ulogic_vector(7 downto 0)); -- code received from PS/2
|
end component;
|
end component;
|
|
|
component ps2_debounce is
|
component ps2_debounce is
|
generic(counter_size: integer := 19); --counter size (19 bits gives 10.5ms with 50mhz clock)
|
generic(counter_size: integer := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
|
port(
|
port(
|
clk: in std_ulogic;
|
clk: in std_ulogic;
|
button: in std_ulogic; --input signal to be debounced
|
button: in std_ulogic; --input signal to be debounced
|
result: out std_ulogic := '0'); --debounced signal
|
result: out std_ulogic := '0'); --debounced signal
|
end component;
|
end component;
|
|
|
component keyboard is
|
component keyboard is
|
generic(
|
generic(
|
clock_frequency: integer := 50000000; -- system clock frequency in hz
|
g: common_generics;
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50MHz)
|
port(
|
port(
|
clk: in std_ulogic; -- system clock input
|
clk: in std_ulogic; -- system clock input
|
rst: in std_ulogic; -- system reset
|
rst: in std_ulogic; -- system reset
|
|
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
|
|
kbd_char_re: in std_ulogic; -- acknowledge kbd_char_buf_new
|
kbd_char_re: in std_ulogic; -- acknowledge kbd_char_buf_new
|
kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
kbd_char_buf: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
kbd_char_buf: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
end component;
|
end component;
|
end package;
|
end package;
|
|
|
------ Keyboard ----------------------------------------------------------------
|
------ Keyboard ----------------------------------------------------------------
|
library ieee;
|
library ieee, work;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use work.kbd_pkg.all;
|
use work.kbd_pkg.all;
|
|
use work.util.common_generics;
|
|
|
entity keyboard is
|
entity keyboard is
|
generic(
|
generic(
|
clock_frequency: integer := 50000000; -- system clock frequency in hz
|
g: common_generics;
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50MHz)
|
port(
|
port(
|
clk: in std_ulogic; -- system clock input
|
clk: in std_ulogic; -- system clock input
|
rst: in std_ulogic; -- system reset
|
rst: in std_ulogic; -- system reset
|
|
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
|
|
kbd_char_re: in std_ulogic; -- acknowledge kbd_char_buf_new
|
kbd_char_re: in std_ulogic; -- acknowledge kbd_char_buf_new
|
kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
kbd_char_buf: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
kbd_char_buf: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
end entity;
|
end entity;
|
|
|
architecture rtl of keyboard is
|
architecture rtl of keyboard is
|
signal kbd_new_c, kbd_new_n: std_ulogic := '0';
|
signal kbd_new_c, kbd_new_n: std_ulogic := '0';
|
signal kbd_new_edge: std_ulogic := '0';
|
signal kbd_new_edge: std_ulogic := '0';
|
signal kbd_new: std_ulogic := '0'; -- new ASCII char available
|
signal kbd_new: std_ulogic := '0'; -- new ASCII char available
|
signal kbd_char: std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char
|
signal kbd_char: std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char
|
signal kbd_char_o: std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char
|
|
begin
|
begin
|
kbd_char_buf_new <= kbd_new_c;
|
kbd_char_buf_new <= kbd_new_c after g.delay;
|
|
|
ps2_next: process(clk, rst)
|
ps2_next: process(clk, rst)
|
begin
|
begin
|
if rst = '1' then
|
if rst = '1' and g.asynchronous_reset then
|
kbd_new_c <= '0';
|
kbd_new_c <= '0' after g.delay;
|
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
kbd_new_c <= kbd_new_n;
|
if rst = '1' and not g.asynchronous_reset then
|
|
kbd_new_c <= '0' after g.delay;
|
|
else
|
|
kbd_new_c <= kbd_new_n after g.delay;
|
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
new_char: entity work.reg
|
new_char: entity work.reg
|
generic map(N => kbd_char'high+1)
|
generic map(g => g, N => kbd_char'length)
|
port map(
|
port map(
|
clk => clk,
|
clk => clk,
|
rst => rst,
|
rst => rst,
|
di => kbd_char,
|
di => kbd_char,
|
we => kbd_new_edge,
|
we => kbd_new_edge,
|
do => kbd_char_o);
|
|
|
|
char_buf: entity work.reg
|
|
generic map(N => kbd_char'high+1)
|
|
port map(
|
|
clk => clk,
|
|
rst => rst,
|
|
di => kbd_char_o,
|
|
we => kbd_char_re,
|
|
do => kbd_char_buf);
|
do => kbd_char_buf);
|
|
|
ps2_proc: process(kbd_new_edge, kbd_new_c, kbd_char_re)
|
ps2_proc: process(kbd_new_edge, kbd_new_c, kbd_char_re)
|
begin
|
begin
|
if kbd_new_edge = '1' then
|
if kbd_new_edge = '1' then
|
kbd_new_n <= '1';
|
kbd_new_n <= '1' after g.delay;
|
elsif kbd_char_re = '1' then
|
elsif kbd_char_re = '1' then
|
kbd_new_n <= '0';
|
kbd_new_n <= '0' after g.delay;
|
else
|
else
|
kbd_new_n <= kbd_new_c;
|
kbd_new_n <= kbd_new_c after g.delay;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- Process a kbd_new into a single edge for the rest of the
|
-- Process a kbd_new into a single edge for the rest of the
|
-- system.
|
-- system.
|
ps2_edge_new_character_0: entity work.rising_edge_detector
|
ps2_edge_new_character_0: entity work.rising_edge_detector
|
|
generic map(g => g)
|
port map(
|
port map(
|
clk => clk,
|
clk => clk,
|
rst => rst,
|
rst => rst,
|
di => kbd_new,
|
di => kbd_new,
|
do => kbd_new_edge);
|
do => kbd_new_edge);
|
|
|
ps2_0: work.kbd_pkg.ps2_kbd_top
|
ps2_0: work.kbd_pkg.ps2_kbd_top
|
generic map(
|
generic map(
|
clock_frequency => clock_frequency,
|
clock_frequency => g.clock_frequency,
|
ps2_debounce_counter_size => ps2_debounce_counter_size)
|
ps2_debounce_counter_size => ps2_debounce_counter_size)
|
port map(
|
port map(
|
clk => clk,
|
clk => clk,
|
ps2_clk => ps2_clk,
|
ps2_clk => ps2_clk,
|
ps2_data => ps2_data,
|
ps2_data => ps2_data,
|
ascii_new => kbd_new,
|
ascii_new => kbd_new,
|
ascii_code => kbd_char);
|
ascii_code => kbd_char);
|
end architecture;
|
end architecture;
|
------ Keyboard ----------------------------------------------------------------
|
------ Keyboard ----------------------------------------------------------------
|
|
|
------ PS2 KBD TOP -------------------------------------------------------------
|
------ PS2 KBD TOP -------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use work.kbd_pkg.all;
|
use work.kbd_pkg.all;
|
|
|
entity ps2_kbd_top is
|
entity ps2_kbd_top is
|
generic(
|
generic(
|
clock_frequency: integer := 50000000; -- system clock frequency in hz
|
clock_frequency: integer := 50000000; -- system clock frequency in Hz
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
|
ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50MHz)
|
port(
|
port(
|
clk: in std_ulogic; -- system clock input
|
clk: in std_ulogic; -- system clock input
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS2 keyboard
|
ascii_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
ascii_new: out std_ulogic := '0'; -- output flag indicating new ascii value
|
ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value
|
end entity;
|
end entity;
|
|
|
architecture rtl of ps2_kbd_top is
|
architecture rtl of ps2_kbd_top is
|
type machine is(ready, new_code, translate, output); -- needed states
|
type machine is(ready, new_code, translate, output); -- needed states
|
signal state: machine; -- state machine
|
signal state: machine; -- state machine
|
signal ps2_code_new: std_ulogic; -- new PS2 code flag from ps2_kbd_core component
|
signal ps2_code_new: std_ulogic; -- new PS2 code flag from ps2_kbd_core component
|
signal ps2_code: std_ulogic_vector(7 downto 0); -- PS2 code input form ps2_kbd_core component
|
signal ps2_code: std_ulogic_vector(7 downto 0); -- PS2 code input form ps2_kbd_core component
|
signal prev_ps2_code_new: std_ulogic := '1'; -- value of ps2_code_new flag on previous clock
|
signal prev_ps2_code_new: std_ulogic := '1'; -- value of ps2_code_new flag on previous clock
|
signal break: std_ulogic := '0'; -- '1' for break code, '0' for make code
|
signal break: std_ulogic := '0'; -- '1' for break code, '0' for make code
|
signal e0_code: std_ulogic := '0'; -- '1' for multi-code commands, '0' for single code commands
|
signal e0_code: std_ulogic := '0'; -- '1' for multi-code commands, '0' for single code commands
|
signal caps_lock: std_ulogic := '0'; -- '1' if caps lock is active, '0' if caps lock is inactive
|
signal caps_lock: std_ulogic := '0'; -- '1' if caps lock is active, '0' if caps lock is inactive
|
signal control_r: std_ulogic := '0'; -- '1' if right control key is held down, else '0'
|
signal control_r: std_ulogic := '0'; -- '1' if right control key is held down, else '0'
|
signal control_l: std_ulogic := '0'; -- '1' if left control key is held down, else '0'
|
signal control_l: std_ulogic := '0'; -- '1' if left control key is held down, else '0'
|
signal shift_r: std_ulogic := '0'; -- '1' if right shift is held down, else '0'
|
signal shift_r: std_ulogic := '0'; -- '1' if right shift is held down, else '0'
|
signal shift_l: std_ulogic := '0'; -- '1' if left shift is held down, else '0'
|
signal shift_l: std_ulogic := '0'; -- '1' if left shift is held down, else '0'
|
signal ascii: std_ulogic_vector(7 downto 0) := x"FF"; -- internal value of ASCII translation
|
signal ascii: std_ulogic_vector(7 downto 0) := x"FF"; -- internal value of ASCII translation
|
|
|
begin
|
begin
|
|
|
-- instantiate PS2 keyboard interface logic
|
-- instantiate PS2 keyboard interface logic
|
ps2_kbd_core_0: work.kbd_pkg.ps2_kbd_core
|
ps2_kbd_core_0: work.kbd_pkg.ps2_kbd_core
|
generic map(
|
generic map(
|
clock_frequency => clock_frequency,
|
clock_frequency => clock_frequency,
|
debounce_counter_size => ps2_debounce_counter_size)
|
debounce_counter_size => ps2_debounce_counter_size)
|
port map(
|
port map(
|
clk => clk,
|
clk => clk,
|
ps2_clk => ps2_clk,
|
ps2_clk => ps2_clk,
|
ps2_data => ps2_data,
|
ps2_data => ps2_data,
|
ps2_code_new => ps2_code_new,
|
ps2_code_new => ps2_code_new,
|
ps2_code => ps2_code);
|
ps2_code => ps2_code);
|
|
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
prev_ps2_code_new <= ps2_code_new; -- keep track of previous ps2_code_new values to determine low-to-high transitions
|
prev_ps2_code_new <= ps2_code_new; -- keep track of previous ps2_code_new values to determine low-to-high transitions
|
case state is
|
case state is
|
|
|
-- ready state: wait for a new PS2 code to be received
|
-- ready state: wait for a new PS2 code to be received
|
when ready =>
|
when ready =>
|
if(prev_ps2_code_new = '0' AND ps2_code_new = '1') then -- new PS2 code received
|
if(prev_ps2_code_new = '0' AND ps2_code_new = '1') then -- new PS2 code received
|
ascii_new <= '0'; -- reset new ASCII code indicator
|
ascii_new <= '0'; -- reset new ASCII code indicator
|
state <= new_code; -- proceed to new_code state
|
state <= new_code; -- proceed to new_code state
|
else -- no new PS2 code received yet
|
else -- no new PS2 code received yet
|
state <= ready; -- remain in ready state
|
state <= ready; -- remain in ready state
|
end if;
|
end if;
|
|
|
-- new_code state: determine what to do with the new PS2 code
|
-- new_code state: determine what to do with the new PS2 code
|
when new_code =>
|
when new_code =>
|
if(ps2_code = x"F0") then -- code indicates that next command is break
|
if(ps2_code = x"F0") then -- code indicates that next command is break
|
break <= '1'; -- set break flag
|
break <= '1'; -- set break flag
|
state <= ready; -- return to ready state to await next PS2 code
|
state <= ready; -- return to ready state to await next PS2 code
|
elsif(ps2_code = x"E0") then -- code indicates multi-key command
|
elsif(ps2_code = x"E0") then -- code indicates multi-key command
|
e0_code <= '1'; -- set multi-code command flag
|
e0_code <= '1'; -- set multi-code command flag
|
state <= ready; -- return to ready state to await next PS2 code
|
state <= ready; -- return to ready state to await next PS2 code
|
else -- code is the last PS2 code in the make/break 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)
|
ascii(7) <= '1'; -- set internal ascii value to unsupported code (for verification)
|
state <= translate; -- proceed to translate state
|
state <= translate; -- proceed to translate state
|
end if;
|
end if;
|
|
|
-- translate state: translate PS2 code to ASCII value
|
-- translate state: translate PS2 code to ASCII value
|
when translate =>
|
when translate =>
|
break <= '0'; -- reset break flag
|
break <= '0'; -- reset break flag
|
e0_code <= '0'; -- reset multi-code command flag
|
e0_code <= '0'; -- reset multi-code command flag
|
|
|
-- handle codes for control, shift, and caps lock
|
-- handle codes for control, shift, and caps lock
|
case ps2_code is
|
case ps2_code is
|
when x"58" => -- caps lock code
|
when x"58" => -- caps lock code
|
if(break = '0') then -- if make command
|
if(break = '0') then -- if make command
|
caps_lock <= NOT caps_lock; -- toggle caps lock
|
caps_lock <= NOT caps_lock; -- toggle caps lock
|
end if;
|
end if;
|
when x"14" => -- code for the control keys
|
when x"14" => -- code for the control keys
|
if(e0_code = '1') then -- code for right control
|
if(e0_code = '1') then -- code for right control
|
control_r <= NOT break; -- update right control flag
|
control_r <= NOT break; -- update right control flag
|
else -- code for left control
|
else -- code for left control
|
control_l <= NOT break; -- update left control flag
|
control_l <= NOT break; -- update left control flag
|
end if;
|
end if;
|
when x"12" => -- left shift code
|
when x"12" => -- left shift code
|
shift_l <= NOT break; -- update left shift flag
|
shift_l <= NOT break; -- update left shift flag
|
when x"59" => -- right shift code
|
when x"59" => -- right shift code
|
shift_r <= NOT break; -- update right shift flag
|
shift_r <= NOT break; -- update right shift flag
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
|
|
-- translate control codes (these do not depend on shift or caps lock)
|
-- translate control codes (these do not depend on shift or caps lock)
|
if(control_l = '1' OR control_r = '1') then
|
if(control_l = '1' OR control_r = '1') then
|
case ps2_code is
|
case ps2_code is
|
when x"1E" => ascii <= x"00"; -- ^@ NUL
|
when x"1E" => ascii <= x"00"; -- ^@ NUL
|
when x"1C" => ascii <= x"01"; -- ^A SOH
|
when x"1C" => ascii <= x"01"; -- ^A SOH
|
when x"32" => ascii <= x"02"; -- ^B STX
|
when x"32" => ascii <= x"02"; -- ^B STX
|
when x"21" => ascii <= x"03"; -- ^C ETX
|
when x"21" => ascii <= x"03"; -- ^C ETX
|
when x"23" => ascii <= x"04"; -- ^D EOT
|
when x"23" => ascii <= x"04"; -- ^D EOT
|
when x"24" => ascii <= x"05"; -- ^E ENQ
|
when x"24" => ascii <= x"05"; -- ^E ENQ
|
when x"2B" => ascii <= x"06"; -- ^F ACK
|
when x"2B" => ascii <= x"06"; -- ^F ACK
|
when x"34" => ascii <= x"07"; -- ^G BEL
|
when x"34" => ascii <= x"07"; -- ^G BEL
|
when x"33" => ascii <= x"08"; -- ^H BS
|
when x"33" => ascii <= x"08"; -- ^H BS
|
when x"43" => ascii <= x"09"; -- ^I HT
|
when x"43" => ascii <= x"09"; -- ^I HT
|
when x"3B" => ascii <= x"0A"; -- ^J LF
|
when x"3B" => ascii <= x"0A"; -- ^J LF
|
when x"42" => ascii <= x"0B"; -- ^K VT
|
when x"42" => ascii <= x"0B"; -- ^K VT
|
when x"4B" => ascii <= x"0C"; -- ^L FF
|
when x"4B" => ascii <= x"0C"; -- ^L FF
|
when x"3A" => ascii <= x"0D"; -- ^M CR
|
when x"3A" => ascii <= x"0D"; -- ^M CR
|
when x"31" => ascii <= x"0E"; -- ^N SO
|
when x"31" => ascii <= x"0E"; -- ^N SO
|
when x"44" => ascii <= x"0F"; -- ^O SI
|
when x"44" => ascii <= x"0F"; -- ^O SI
|
when x"4D" => ascii <= x"10"; -- ^P DLE
|
when x"4D" => ascii <= x"10"; -- ^P DLE
|
when x"15" => ascii <= x"11"; -- ^Q DC1
|
when x"15" => ascii <= x"11"; -- ^Q DC1
|
when x"2D" => ascii <= x"12"; -- ^R DC2
|
when x"2D" => ascii <= x"12"; -- ^R DC2
|
when x"1B" => ascii <= x"13"; -- ^S DC3
|
when x"1B" => ascii <= x"13"; -- ^S DC3
|
when x"2C" => ascii <= x"14"; -- ^T DC4
|
when x"2C" => ascii <= x"14"; -- ^T DC4
|
when x"3C" => ascii <= x"15"; -- ^U NAK
|
when x"3C" => ascii <= x"15"; -- ^U NAK
|
when x"2A" => ascii <= x"16"; -- ^V SYN
|
when x"2A" => ascii <= x"16"; -- ^V SYN
|
when x"1D" => ascii <= x"17"; -- ^W ETB
|
when x"1D" => ascii <= x"17"; -- ^W ETB
|
when x"22" => ascii <= x"18"; -- ^X CAN
|
when x"22" => ascii <= x"18"; -- ^X CAN
|
when x"35" => ascii <= x"19"; -- ^Y EM
|
when x"35" => ascii <= x"19"; -- ^Y EM
|
when x"1A" => ascii <= x"1A"; -- ^Z SUB
|
when x"1A" => ascii <= x"1A"; -- ^Z SUB
|
when x"54" => ascii <= x"1B"; -- ^[ ESC
|
when x"54" => ascii <= x"1B"; -- ^[ ESC
|
when x"5D" => ascii <= x"1C"; -- ^\ FS
|
when x"5D" => ascii <= x"1C"; -- ^\ FS
|
when x"5B" => ascii <= x"1D"; -- ^] GS
|
when x"5B" => ascii <= x"1D"; -- ^] GS
|
when x"36" => ascii <= x"1E"; -- ^^ RS
|
when x"36" => ascii <= x"1E"; -- ^^ RS
|
when x"4E" => ascii <= x"1F"; -- ^_ US
|
when x"4E" => ascii <= x"1F"; -- ^_ US
|
when x"4A" => ascii <= x"7F"; -- ^? DEL
|
when x"4A" => ascii <= x"7F"; -- ^? DEL
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
else -- if control keys are not pressed
|
else -- if control keys are not pressed
|
|
|
-- translate characters that do not depend on shift, or caps lock
|
-- translate characters that do not depend on shift, or caps lock
|
case ps2_code is
|
case ps2_code is
|
when x"29" => ascii <= x"20"; -- space
|
when x"29" => ascii <= x"20"; -- space
|
when x"66" => ascii <= x"08"; -- backspace (BS control code)
|
when x"66" => ascii <= x"08"; -- backspace (BS control code)
|
when x"0D" => ascii <= x"09"; -- tab (HT control code)
|
when x"0D" => ascii <= x"09"; -- tab (HT control code)
|
when x"5A" => ascii <= x"0D"; -- enter (CR control code)
|
when x"5A" => ascii <= x"0D"; -- enter (CR control code)
|
when x"76" => ascii <= x"1B"; -- escape (ESC control code)
|
when x"76" => ascii <= x"1B"; -- escape (ESC control code)
|
when x"71" =>
|
when x"71" =>
|
if(e0_code = '1') then -- ps2 code for delete is a multi-key code
|
if(e0_code = '1') then -- ps2 code for delete is a multi-key code
|
ascii <= x"7F"; -- delete
|
ascii <= x"7F"; -- delete
|
end if;
|
end if;
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
|
|
-- translate letters (these depend on both shift and caps lock)
|
-- translate letters (these depend on both shift and caps lock)
|
if((shift_r = '0' AND shift_l = '0' AND caps_lock = '0') OR
|
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
|
((shift_r = '1' OR shift_l = '1') AND caps_lock = '1')) then -- letter is lowercase
|
case ps2_code is
|
case ps2_code is
|
when x"1C" => ascii <= x"61"; -- a
|
when x"1C" => ascii <= x"61"; -- a
|
when x"32" => ascii <= x"62"; -- b
|
when x"32" => ascii <= x"62"; -- b
|
when x"21" => ascii <= x"63"; -- c
|
when x"21" => ascii <= x"63"; -- c
|
when x"23" => ascii <= x"64"; -- d
|
when x"23" => ascii <= x"64"; -- d
|
when x"24" => ascii <= x"65"; -- e
|
when x"24" => ascii <= x"65"; -- e
|
when x"2B" => ascii <= x"66"; -- f
|
when x"2B" => ascii <= x"66"; -- f
|
when x"34" => ascii <= x"67"; -- g
|
when x"34" => ascii <= x"67"; -- g
|
when x"33" => ascii <= x"68"; -- h
|
when x"33" => ascii <= x"68"; -- h
|
when x"43" => ascii <= x"69"; -- i
|
when x"43" => ascii <= x"69"; -- i
|
when x"3B" => ascii <= x"6A"; -- j
|
when x"3B" => ascii <= x"6A"; -- j
|
when x"42" => ascii <= x"6B"; -- k
|
when x"42" => ascii <= x"6B"; -- k
|
when x"4B" => ascii <= x"6C"; -- l
|
when x"4B" => ascii <= x"6C"; -- l
|
when x"3A" => ascii <= x"6D"; -- m
|
when x"3A" => ascii <= x"6D"; -- m
|
when x"31" => ascii <= x"6E"; -- n
|
when x"31" => ascii <= x"6E"; -- n
|
when x"44" => ascii <= x"6F"; -- o
|
when x"44" => ascii <= x"6F"; -- o
|
when x"4D" => ascii <= x"70"; -- p
|
when x"4D" => ascii <= x"70"; -- p
|
when x"15" => ascii <= x"71"; -- q
|
when x"15" => ascii <= x"71"; -- q
|
when x"2D" => ascii <= x"72"; -- r
|
when x"2D" => ascii <= x"72"; -- r
|
when x"1B" => ascii <= x"73"; -- s
|
when x"1B" => ascii <= x"73"; -- s
|
when x"2C" => ascii <= x"74"; -- t
|
when x"2C" => ascii <= x"74"; -- t
|
when x"3C" => ascii <= x"75"; -- u
|
when x"3C" => ascii <= x"75"; -- u
|
when x"2A" => ascii <= x"76"; -- v
|
when x"2A" => ascii <= x"76"; -- v
|
when x"1D" => ascii <= x"77"; -- w
|
when x"1D" => ascii <= x"77"; -- w
|
when x"22" => ascii <= x"78"; -- x
|
when x"22" => ascii <= x"78"; -- x
|
when x"35" => ascii <= x"79"; -- y
|
when x"35" => ascii <= x"79"; -- y
|
when x"1A" => ascii <= x"7A"; -- z
|
when x"1A" => ascii <= x"7A"; -- z
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
else -- letter is uppercase
|
else -- letter is uppercase
|
case ps2_code is
|
case ps2_code is
|
when x"1C" => ascii <= x"41"; -- A
|
when x"1C" => ascii <= x"41"; -- A
|
when x"32" => ascii <= x"42"; -- B
|
when x"32" => ascii <= x"42"; -- B
|
when x"21" => ascii <= x"43"; -- C
|
when x"21" => ascii <= x"43"; -- C
|
when x"23" => ascii <= x"44"; -- D
|
when x"23" => ascii <= x"44"; -- D
|
when x"24" => ascii <= x"45"; -- E
|
when x"24" => ascii <= x"45"; -- E
|
when x"2B" => ascii <= x"46"; -- F
|
when x"2B" => ascii <= x"46"; -- F
|
when x"34" => ascii <= x"47"; -- G
|
when x"34" => ascii <= x"47"; -- G
|
when x"33" => ascii <= x"48"; -- H
|
when x"33" => ascii <= x"48"; -- H
|
when x"43" => ascii <= x"49"; -- I
|
when x"43" => ascii <= x"49"; -- I
|
when x"3B" => ascii <= x"4A"; -- J
|
when x"3B" => ascii <= x"4A"; -- J
|
when x"42" => ascii <= x"4B"; -- K
|
when x"42" => ascii <= x"4B"; -- K
|
when x"4B" => ascii <= x"4C"; -- L
|
when x"4B" => ascii <= x"4C"; -- L
|
when x"3A" => ascii <= x"4D"; -- M
|
when x"3A" => ascii <= x"4D"; -- M
|
when x"31" => ascii <= x"4E"; -- N
|
when x"31" => ascii <= x"4E"; -- N
|
when x"44" => ascii <= x"4F"; -- O
|
when x"44" => ascii <= x"4F"; -- O
|
when x"4D" => ascii <= x"50"; -- P
|
when x"4D" => ascii <= x"50"; -- P
|
when x"15" => ascii <= x"51"; -- Q
|
when x"15" => ascii <= x"51"; -- Q
|
when x"2D" => ascii <= x"52"; -- R
|
when x"2D" => ascii <= x"52"; -- R
|
when x"1B" => ascii <= x"53"; -- S
|
when x"1B" => ascii <= x"53"; -- S
|
when x"2C" => ascii <= x"54"; -- T
|
when x"2C" => ascii <= x"54"; -- T
|
when x"3C" => ascii <= x"55"; -- U
|
when x"3C" => ascii <= x"55"; -- U
|
when x"2A" => ascii <= x"56"; -- V
|
when x"2A" => ascii <= x"56"; -- V
|
when x"1D" => ascii <= x"57"; -- W
|
when x"1D" => ascii <= x"57"; -- W
|
when x"22" => ascii <= x"58"; -- X
|
when x"22" => ascii <= x"58"; -- X
|
when x"35" => ascii <= x"59"; -- Y
|
when x"35" => ascii <= x"59"; -- Y
|
when x"1A" => ascii <= x"5A"; -- Z
|
when x"1A" => ascii <= x"5A"; -- Z
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- translate numbers and symbols (these depend on shift but not caps lock)
|
-- 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
|
if(shift_l = '1' OR shift_r = '1') then -- key's secondary character is desired
|
case ps2_code is
|
case ps2_code is
|
when x"16" => ascii <= x"21"; -- |
|
when x"16" => ascii <= x"21"; -- |
|
when x"52" => ascii <= x"22"; -- "
|
when x"52" => ascii <= x"22"; -- "
|
when x"26" => ascii <= x"23"; -- #
|
when x"26" => ascii <= x"23"; -- #
|
when x"25" => ascii <= x"24"; -- $
|
when x"25" => ascii <= x"24"; -- $
|
when x"2E" => ascii <= x"25"; -- %
|
when x"2E" => ascii <= x"25"; -- %
|
when x"3D" => ascii <= x"26"; -- &
|
when x"3D" => ascii <= x"26"; -- &
|
when x"46" => ascii <= x"28"; -- (
|
when x"46" => ascii <= x"28"; -- (
|
when x"45" => ascii <= x"29"; -- )
|
when x"45" => ascii <= x"29"; -- )
|
when x"3E" => ascii <= x"2A"; -- *
|
when x"3E" => ascii <= x"2A"; -- *
|
when x"55" => ascii <= x"2B"; -- +
|
when x"55" => ascii <= x"2B"; -- +
|
when x"4C" => ascii <= x"3A"; -- :
|
when x"4C" => ascii <= x"3A"; -- :
|
when x"41" => ascii <= x"3C"; -- <
|
when x"41" => ascii <= x"3C"; -- <
|
when x"49" => ascii <= x"3E"; -- >
|
when x"49" => ascii <= x"3E"; -- >
|
when x"4A" => ascii <= x"3F"; -- ?
|
when x"4A" => ascii <= x"3F"; -- ?
|
when x"1E" => ascii <= x"40"; -- @
|
when x"1E" => ascii <= x"40"; -- @
|
when x"36" => ascii <= x"5E"; -- ^
|
when x"36" => ascii <= x"5E"; -- ^
|
when x"4E" => ascii <= x"5F"; -- _
|
when x"4E" => ascii <= x"5F"; -- _
|
when x"54" => ascii <= x"7B"; -- {
|
when x"54" => ascii <= x"7B"; -- {
|
when x"5D" => ascii <= x"7C"; -- |
|
when x"5D" => ascii <= x"7C"; -- |
|
when x"5B" => ascii <= x"7D"; -- }
|
when x"5B" => ascii <= x"7D"; -- }
|
when x"0E" => ascii <= x"7E"; -- ~
|
when x"0E" => ascii <= x"7E"; -- ~
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
else -- key's primary character is desired
|
else -- key's primary character is desired
|
case ps2_code is
|
case ps2_code is
|
when x"45" => ascii <= x"30"; -- 0
|
when x"45" => ascii <= x"30"; -- 0
|
when x"16" => ascii <= x"31"; -- 1
|
when x"16" => ascii <= x"31"; -- 1
|
when x"1E" => ascii <= x"32"; -- 2
|
when x"1E" => ascii <= x"32"; -- 2
|
when x"26" => ascii <= x"33"; -- 3
|
when x"26" => ascii <= x"33"; -- 3
|
when x"25" => ascii <= x"34"; -- 4
|
when x"25" => ascii <= x"34"; -- 4
|
when x"2E" => ascii <= x"35"; -- 5
|
when x"2E" => ascii <= x"35"; -- 5
|
when x"36" => ascii <= x"36"; -- 6
|
when x"36" => ascii <= x"36"; -- 6
|
when x"3D" => ascii <= x"37"; -- 7
|
when x"3D" => ascii <= x"37"; -- 7
|
when x"3E" => ascii <= x"38"; -- 8
|
when x"3E" => ascii <= x"38"; -- 8
|
when x"46" => ascii <= x"39"; -- 9
|
when x"46" => ascii <= x"39"; -- 9
|
when x"52" => ascii <= x"27"; -- '
|
when x"52" => ascii <= x"27"; -- '
|
when x"41" => ascii <= x"2C"; -- ,
|
when x"41" => ascii <= x"2C"; -- ,
|
when x"4E" => ascii <= x"2D"; -- -
|
when x"4E" => ascii <= x"2D"; -- -
|
when x"49" => ascii <= x"2E"; -- .
|
when x"49" => ascii <= x"2E"; -- .
|
when x"4A" => ascii <= x"2F"; -- /
|
when x"4A" => ascii <= x"2F"; -- /
|
when x"4C" => ascii <= x"3B"; -- ;
|
when x"4C" => ascii <= x"3B"; -- ;
|
when x"55" => ascii <= x"3D"; -- =
|
when x"55" => ascii <= x"3D"; -- =
|
when x"54" => ascii <= x"5B"; -- [
|
when x"54" => ascii <= x"5B"; -- [
|
when x"5D" => ascii <= x"5C"; -- \
|
when x"5D" => ascii <= x"5C"; -- \
|
when x"5B" => ascii <= x"5D"; -- ]
|
when x"5B" => ascii <= x"5D"; -- ]
|
when x"0E" => ascii <= x"60"; -- `
|
when x"0E" => ascii <= x"60"; -- `
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
end if;
|
end if;
|
|
|
if(break = '0') then -- the code is a make
|
if(break = '0') then -- the code is a make
|
state <= output; -- proceed to output state
|
state <= output; -- proceed to output state
|
else -- code is a break
|
else -- code is a break
|
state <= ready; -- return to ready state to await next PS2 code
|
state <= ready; -- return to ready state to await next PS2 code
|
end if;
|
end if;
|
|
|
-- output state: verify the code is valid and output the ASCII value
|
-- output state: verify the code is valid and output the ASCII value
|
when output =>
|
when output =>
|
if(ascii(7) = '0') then -- the PS2 code has an ASCII output
|
if(ascii(7) = '0') then -- the PS2 code has an ASCII output
|
ascii_new <= '1'; -- set flag indicating new ASCII output
|
ascii_new <= '1'; -- set flag indicating new ASCII output
|
ascii_code <= ascii(6 downto 0); -- output the ASCII value
|
ascii_code <= ascii(6 downto 0); -- output the ASCII value
|
end if;
|
end if;
|
state <= ready; -- return to ready state to await next PS2 code
|
state <= ready; -- return to ready state to await next PS2 code
|
|
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
end;
|
end;
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- FileName: ps2_kbd_core.vhd
|
-- FileName: ps2_kbd_core.vhd
|
-- Dependencies: debounce.vhd
|
-- Dependencies: debounce.vhd
|
-- Design Software: Quartus II 32-bit Version 12.1 Build 177 SJ Full Version
|
-- Design Software: Quartus II 32-bit Version 12.1 Build 177 SJ Full Version
|
--
|
--
|
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
--
|
--
|
-- Version History
|
-- Version History
|
-- Version 1.0 11/25/2013 Scott Larson
|
-- Version 1.0 11/25/2013 Scott Larson
|
-- Initial Public Release
|
-- Initial Public Release
|
--
|
--
|
-- @note This file has been modified from the original one found at
|
-- @note This file has been modified from the original one found at
|
-- <https://eewiki.net/pages/viewpage.action?pageId=28279002>
|
-- <https://eewiki.net/pages/viewpage.action?pageId=28279002>
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
|
|
entity ps2_kbd_core is
|
entity ps2_kbd_core is
|
generic(
|
generic(
|
clock_frequency: integer := 50000000; -- system clock frequency in hz
|
clock_frequency: integer := 50000000; -- system clock frequency in Hz
|
debounce_counter_size: integer := 8); -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50mhz)
|
debounce_counter_size: integer := 8); -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50MHz)
|
port(
|
port(
|
clk: in std_ulogic; -- system clock
|
clk: in std_ulogic; -- system clock
|
ps2_clk: in std_ulogic; -- clock signal from PS/2 keyboard
|
ps2_clk: in std_ulogic; -- clock signal from PS/2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS/2 keyboard
|
ps2_data: in std_ulogic; -- data signal from PS/2 keyboard
|
ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus
|
ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus
|
ps2_code: out std_ulogic_vector(7 downto 0)); -- code received from PS/2
|
ps2_code: out std_ulogic_vector(7 downto 0)); -- code received from PS/2
|
end entity;
|
end entity;
|
|
|
architecture rtl of ps2_kbd_core is
|
architecture rtl of ps2_kbd_core is
|
|
|
signal sync_ffs: std_ulogic_vector(1 downto 0); -- synchronizer flip-flops for PS/2 signals
|
signal sync_ffs: std_ulogic_vector(1 downto 0); -- synchronizer flip-flops for PS/2 signals
|
signal ps2_clk_int: std_ulogic; -- debounced clock signal from PS/2 keyboard
|
signal ps2_clk_int: std_ulogic; -- debounced clock signal from PS/2 keyboard
|
|
|
attribute buffer_type: string;
|
attribute buffer_type: string;
|
attribute buffer_type of ps2_clk_int: signal is "BUFG";
|
attribute buffer_type of ps2_clk_int: signal is "BUFG";
|
|
|
signal ps2_data_int: std_ulogic; -- debounced data signal from PS/2 keyboard
|
signal ps2_data_int: std_ulogic; -- debounced data signal from PS/2 keyboard
|
signal ps2_word: std_ulogic_vector(10 downto 0); -- stores the ps2 data word
|
signal ps2_word: std_ulogic_vector(10 downto 0); -- stores the ps2 data word
|
signal parity_error: std_ulogic; -- validate parity, start, and stop bits
|
signal parity_error: std_ulogic; -- validate parity, start, and stop bits
|
signal count_idle: integer range 0 to clock_frequency/18000; --counter to determine PS/2 is idle
|
signal count_idle: integer range 0 to clock_frequency/18000; --counter to determine PS/2 is idle
|
|
|
begin
|
begin
|
|
|
--synchronizer flip-flops
|
--synchronizer flip-flops
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if rising_edge(clk) then -- rising edge of system clock
|
if rising_edge(clk) then -- rising edge of system clock
|
sync_ffs(0) <= ps2_clk; -- synchronize PS/2 clock signal
|
sync_ffs(0) <= ps2_clk; -- synchronize PS/2 clock signal
|
sync_ffs(1) <= ps2_data; -- synchronize PS/2 data signal
|
sync_ffs(1) <= ps2_data; -- synchronize PS/2 data signal
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- debounce ps2 input signals
|
-- debounce ps2 input signals
|
debounce_ps2_clk: work.kbd_pkg.ps2_debounce
|
debounce_ps2_clk: work.kbd_pkg.ps2_debounce
|
generic map(counter_size => debounce_counter_size)
|
generic map(counter_size => debounce_counter_size)
|
port map(clk => clk, button => sync_ffs(0), result => ps2_clk_int);
|
port map(clk => clk, button => sync_ffs(0), result => ps2_clk_int);
|
|
|
debounce_ps2_data: work.kbd_pkg.ps2_debounce
|
debounce_ps2_data: work.kbd_pkg.ps2_debounce
|
generic map(counter_size => debounce_counter_size)
|
generic map(counter_size => debounce_counter_size)
|
port map(clk => clk, button => sync_ffs(1), result => ps2_data_int);
|
port map(clk => clk, button => sync_ffs(1), result => ps2_data_int);
|
|
|
-- input ps2 data
|
-- input ps2 data
|
process(ps2_clk_int)
|
process(ps2_clk_int)
|
begin
|
begin
|
if(ps2_clk_int'event and ps2_clk_int = '0') then -- falling edge of ps2 clock
|
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
|
ps2_word <= ps2_data_int & ps2_word(10 downto 1); -- shift in ps2 data bit
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- verify that parity, start, and stop bits are all correct
|
-- verify that parity, start, and stop bits are all correct
|
parity_error <= not (not ps2_word(0) and ps2_word(10) and (ps2_word(9) xor ps2_word(8) xor
|
parity_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(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)));
|
ps2_word(2) xor ps2_word(1)));
|
|
|
-- determine if ps2 port is idle (i.e. last transaction is finished) and output result
|
-- determine if ps2 port is idle (i.e. last transaction is finished) and output result
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if rising_edge(clk) then -- rising edge of system clock
|
if rising_edge(clk) then -- rising edge of system clock
|
if(ps2_clk_int = '0') then -- low ps2 clock, PS/2 is active
|
if(ps2_clk_int = '0') then -- low ps2 clock, PS/2 is active
|
count_idle <= 0; -- reset idle counter
|
count_idle <= 0; -- reset idle counter
|
elsif(count_idle /= clock_frequency/18_000) then -- ps2 clock has been high less than a half clock period (<55us)
|
elsif(count_idle /= clock_frequency/18_000) then -- ps2 clock has been high less than a half clock period (<55us)
|
count_idle <= count_idle + 1; -- continue counting
|
count_idle <= count_idle + 1; -- continue counting
|
end if;
|
end if;
|
|
|
if(count_idle = clock_frequency/18_000 and parity_error = '0') then -- idle threshold reached and no errors detected
|
if(count_idle = clock_frequency/18_000 and parity_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_new <= '1'; -- set flag that new PS/2 code is available
|
ps2_code <= ps2_word(8 downto 1); -- output new PS/2 code
|
ps2_code <= ps2_word(8 downto 1); -- output new PS/2 code
|
else -- PS/2 port active or error detected
|
else -- PS/2 port active or error detected
|
ps2_code_new <= '0'; -- set flag that PS/2 transaction is in progress
|
ps2_code_new <= '0'; -- set flag that PS/2 transaction is in progress
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
end;
|
end;
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- FileName: (originally) debounce.vhd
|
-- FileName: (originally) debounce.vhd
|
-- Dependencies: none
|
-- Dependencies: none
|
-- Design Software: Quartus II 32-bit Version 11.1 Build 173 SJ Full Version
|
-- Design Software: Quartus II 32-bit Version 11.1 Build 173 SJ Full Version
|
--
|
--
|
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
--
|
--
|
-- Version History
|
-- Version History
|
-- Version 1.0 3/26/2012 Scott Larson
|
-- Version 1.0 3/26/2012 Scott Larson
|
-- Initial Public Release
|
-- Initial Public Release
|
--
|
--
|
-- @note This file has been modified from the original one found
|
-- @note This file has been modified from the original one found
|
-- on the web from: <https://eewiki.net/pages/viewpage.action?pageId=28279002>
|
-- on the web from: <https://eewiki.net/pages/viewpage.action?pageId=28279002>
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
|
entity ps2_debounce is
|
entity ps2_debounce is
|
generic(counter_size: integer := 19); --counter size (19 bits gives 10.5ms with 50mhz clock)
|
generic(counter_size: integer := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
|
port(
|
port(
|
clk: in std_ulogic;
|
clk: in std_ulogic;
|
button: in std_ulogic; --input signal to be debounced
|
button: in std_ulogic; --input signal to be debounced
|
result: out std_ulogic := '0'); --debounced signal
|
result: out std_ulogic := '0'); --debounced signal
|
end entity;
|
end entity;
|
|
|
architecture rtl of ps2_debounce is
|
architecture rtl of ps2_debounce is
|
signal flipflops: std_ulogic_vector(1 downto 0); --input flip flops
|
signal flipflops: std_ulogic_vector(1 downto 0); --input flip flops
|
signal counter_set: std_ulogic; --sync reset to zero
|
signal counter_set: std_ulogic; --sync reset to zero
|
signal counter_out: unsigned(counter_size downto 0) := (others => '0'); --counter output
|
signal counter_out: unsigned(counter_size downto 0) := (others => '0'); --counter output
|
begin
|
begin
|
|
|
counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter
|
counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter
|
|
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
flipflops(0) <= button;
|
flipflops(0) <= button;
|
flipflops(1) <= flipflops(0);
|
flipflops(1) <= flipflops(0);
|
if(counter_set = '1') then --reset counter because input is changing
|
if counter_set = '1' then --reset counter because input is changing
|
counter_out <= (others => '0');
|
counter_out <= (others => '0');
|
elsif(counter_out(counter_size) = '0') then --stable input time is not yet met
|
elsif counter_out(counter_size) = '0' then --stable input time is not yet met
|
counter_out <= counter_out + 1;
|
counter_out <= counter_out + 1;
|
else --stable input time is met
|
else --stable input time is met
|
result <= flipflops(1);
|
result <= flipflops(1);
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
end;
|
end;
|
|
|
|
|