📄 keyboardhandler.vhd
字号:
--Keyboard controller
--Reads the scan codes from the PS/2 keyboard and stores them in a FIFO buffer
--Based on the sample code available from the Digilent(R) Inc. website
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity KeyboardHandler is
generic ( buffer_size: positive := 32 );
Port ( KEYBOARD_CLK : in std_logic;
KEYBOARD_DATA : in std_logic;
RESET : in std_logic;
CLK : in std_logic; --Should be 50 MHz!
FIRST_CHAR_INDEX : out std_logic_vector(7 downto 0);
FIRST_FREE_INDEX : out std_logic_vector(7 downto 0);
CHAR_INDEX : in std_logic_vector(7 downto 0);
CHAR_DATA : out std_logic_vector(7 downto 0);
READ_FIRST_CHAR : out std_logic_vector(7 downto 0);
READ_FIRST_CHAR_STROBE : in std_logic);
end KeyboardHandler;
architecture Behavioral of KeyboardHandler is
type buff_array_type is array (buffer_size-1 downto 0) of std_logic_vector (7 downto 0);
signal clkDiv : std_logic_vector (12 downto 0);
signal pclk : std_logic;
signal KDI, KCI : std_logic;
signal DFF1, DFF2 : std_logic;
signal shiftRegSig1: std_logic_vector(10 downto 0);
signal shiftRegSig2: std_logic_vector(10 downto 1);
signal CharBuffer: buff_array_type;
signal FirstCharIndex, FirstFreeIndex: std_logic_vector (7 downto 0);
signal buffer_map: std_logic_vector(7 downto 0);
begin
--Used to normalize the buffer counters when they are modified,
--so that they remain in the domain 0..buffer_size - 1
buffer_map <= conv_std_logic_vector(buffer_size - 1, 8);
--Divide the clock so that we can synchronize with the PS/2 clock
CLKDivider: Process (CLK)
begin
if (CLK = '1' and CLK'Event) then
clkDiv <= clkDiv +1;
end if;
end Process;
pclk <= clkDiv(3);
FIRST_CHAR_INDEX <= FirstCharIndex;
FIRST_FREE_INDEX <= FirstFreeIndex;
process (CHAR_INDEX)
begin
CHAR_DATA <= CharBuffer( conv_integer(UNSIGNED(CHAR_INDEX)) );
end process;
READ_FIRST_CHAR <= CharBuffer( conv_integer(UNSIGNED(FirstCharIndex - '1')) );
--Buffer the keyboard data
Process (pclk, RESET, KEYBOARD_CLK, KEYBOARD_DATA)
begin
if(RESET = '1') then
DFF1 <= '0'; DFF2 <= '0'; KDI <= '0'; KCI <= '0';
else
if (pclk = '1' and pclk'Event) then
DFF1 <= KEYBOARD_DATA; KDI <= DFF1; DFF2 <= KEYBOARD_CLK; KCI <= DFF2;
end if;
end if;
end process;
--Shift Registers used to clock in scan codes from PS2--
Process(KDI, KCI, RESET) --DFF2 carries KD and DFF4, and DFF4 carries KC
begin
if (RESET = '1') then
ShiftRegSig1 <= (others => '0');
ShiftRegSig2 <= (others => '0');
else
if (KCI = '0' and KCI'Event) then
ShiftRegSig1(10 downto 0) <= KDI & ShiftRegSig1(10 downto 1);
ShiftRegSig2(10 downto 1) <= ShiftRegSig1(0) & ShiftRegSig2(10 downto 2);
end if;
end if;
end process;
--Reading out the scan code from the shift register and storing it
--In the buffer when necessarry
process(ShiftRegSig1, ShiftRegSig2, RESET, KCI)
begin
if(RESET = '1')then
FirstFreeIndex <= (others => '0');
else
if(KCI'event and KCI = '1' and ShiftRegSig2(8 downto 1) = "11110000")then
CharBuffer( conv_integer(UNSIGNED(FirstFreeIndex)) ) <= ShiftRegSig1(8 downto 1);
FirstFreeIndex <= (FirstFreeIndex + '1') AND buffer_map;
end if;
end if;
end Process;
--The read first available char process. It reads out the first available
--char (scancode) from the FIFO buffer and increases the start counter
--(actually this process only implements the second part, the first part
--is done at the beginning)
process (RESET, READ_FIRST_CHAR_STROBE)
begin
if (RESET = '1') then
FirstCharIndex <= (others => '0');
else
if (READ_FIRST_CHAR_STROBE'event and READ_FIRST_CHAR_STROBE = '1') then
if not (FirstFreeIndex = FirstCharIndex) then
FirstCharIndex <= (FirstCharIndex + '1') AND buffer_map;
end if;
end if;
end if;
end process;
end Behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -