📄 keyscan.vhd
字号:
-----------------------------------------------------------------------
--
-- Original Code Copyright (c) 1999 by Esperan. All rights reserved.
-- www.esperan.com
--
-- This source file may be used and distributed without restriction
-- provided that this copyright statement is not removed from the file
-- and that any derivative work contains this copyright notice.
--
-- Esperan VHDL Alarm Clock Lab Exercise Design V5.0
--
-- Keyscan.vhd
-- Keypad scanner to detect pressed keys
--
-- This block scans the matrix keypad columns with a
-- "walking zero" pattern, and monitors the keypad
-- rows for a '0' value which indicates that a key
-- has been pressed. If a '0' is found the column/row
-- value is stored and compared with the stored value
-- from the last scan cycle to debounce the keypad. If
-- the column/row value is the same for 2 successive scan
-- cycles the keypress is decoded into either a key value
-- (0-9) or a alarm button (*) or time button (#)
-- assertion.
--
-- This block also includes a key buffer which stores the
-- last 4 keys pressed. New key values are stored in the
-- buffer when the SHIFT input is pulsed (SHIFT is generated
-- by the A_FSM block which detects if a new key has been
-- pressed).
--
----------------------------------------------------
Library IEEE;
use IEEE.Std_Logic_1164.all;
entity KEYSCAN is
port( CLK : in std_logic;
RESET : in std_logic;
SHIFT : in std_logic;
ROWS : in std_logic_vector(3 downto 0);
COLUMNS : out std_logic_vector(2 downto 0);
KEY : out std_logic_vector(3 downto 0);
KEY_BUFFER_0 : out std_logic_vector(3 downto 0);
KEY_BUFFER_1 : out std_logic_vector(3 downto 0);
KEY_BUFFER_2 : out std_logic_vector(3 downto 0);
KEY_BUFFER_3 : out std_logic_vector(3 downto 0);
TIME_BUTTON : out std_logic;
ALARM_BUTTON : out std_logic);
end KEYSCAN;
architecture RTL of KEYSCAN is
-- intermediate signal for COLUMNS output
signal I_COLUMNS : std_logic_vector(2 downto 0);
-- signals to store two column/row values, from the
-- current scan cycle and the previous scan cycle
signal NEW_ROW, OLD_ROW : std_logic_vector(3 downto 0);
signal NEW_COLUMN, OLD_COLUMN : std_logic_vector(2 downto 0);
-- intermediate signals for the current key value output, KEY, and
-- the 4 stored key values in the key buffer
signal I_KEY,
I_KEY_BUFFER_0,
I_KEY_BUFFER_1,
I_KEY_BUFFER_2,
I_KEY_BUFFER_3 : std_logic_vector(3 downto 0);
-- constant for the "no key" value output when there are no keys
-- pressed on the keypad.
constant NO_KEY: std_logic_vector(3 downto 0) := "1010"; -- decimal 10
begin
------------------------------------------------------------------
-- This process generates the "walking zero" pattern which scans
-- the keypad. A Scan cycle takes 4 clock cycles of the 256Hz input
-- clock; 1 clock cycle to scan each column with a '0' and a final
-- cycle (I_COLUMNS = "111") when the key values are debounced and
-- decoded.
------------------------------------------------------------------
COLUMN_SCAN: process (CLK, RESET)
begin
if RESET = '1' then
I_COLUMNS <= "000"; -- need to reset to all zero for
-- XC5200 family parts; no preset
elsif CLK'event and CLK = '1' then
case I_COLUMNS is
when "111" => I_COLUMNS <= "011";
when "011" => I_COLUMNS <= "101";
when "101" => I_COLUMNS <= "110";
when "110" => I_COLUMNS <= "111";
when others => I_COLUMNS <= "111";
end case;
end if;
end process;
-- Connect intermediate signal to output port
COLUMNS <= I_COLUMNS;
------------------------------------------------------------------
-- This process scans the keypad rows for '0' which would indicate
-- a key has been pressed. If a '0' is detected the column/row value
-- is stored. In the final clock period in a scan cycle
-- (I_COLUMN = "111") any new column/row value is compared with that
-- from the previous scan cycle (this filters out any spurious '0'
-- due to key bounces). If the values are the same then the key
-- values is decoded.
------------------------------------------------------------------
ROW_SCAN: process (CLK, RESET)
begin
if RESET = '1' then
NEW_ROW <= "0000";
OLD_ROW <= "0000";
NEW_COLUMN <= "000";
OLD_COLUMN <= "000";
I_KEY <= "1010"; -- reset to NOKEY value
TIME_BUTTON <= '0';
ALARM_BUTTON <= '0';
elsif CLK'event and CLK = '1' then
-- If any ROW bits are zero a key may have been pressed so store
-- column/row values.
if ROWS(0) = '0' or ROWS(1) = '0' or ROWS(2) = '0'
or ROWS(3) = '0' then
NEW_ROW <= ROWS;
NEW_COLUMN <= I_COLUMNS;
end if;
if I_COLUMNS = "111" then -- last clock period in a scan cycle
TIME_BUTTON <= '0'; -- set default values for outputs
ALARM_BUTTON <= '0';
I_KEY <= NO_KEY;
-- debounce keys by comparing old and new values
-- if same then decode key value
if (NEW_ROW = OLD_ROW) and (NEW_COLUMN = OLD_COLUMN) then
case OLD_COLUMN is
when "011" =>
case OLD_ROW is
when "0111" => I_KEY <= "0001"; -- 1
when "1011" => I_KEY <= "0100"; -- 4
when "1101" => I_KEY <= "0111"; -- 7
when "1110" => ALARM_BUTTON <= '1'; -- '*' = alarm button
when others => NULL;
end case;
when "101" =>
case OLD_ROW is
when "0111" => I_KEY <= "0010"; -- 2
when "1011" => I_KEY <= "0101"; -- 5
when "1101" => I_KEY <= "1000"; -- 8
when "1110" => I_KEY <= "0000"; -- 0
when others => NULL;
end case;
when "110" =>
case OLD_ROW is
when "0111" => I_KEY <= "0011"; -- 3
when "1011" => I_KEY <= "0110"; -- 6
when "1101" => I_KEY <= "1001"; -- 9
when "1110" => TIME_BUTTON <= '1'; -- '#' = time button
when others => NULL;
end case;
when others => NULL;
end case;
end if;
-- update the stored old row and column and reset the
-- NEW row/column ready for the next scan cycle
OLD_ROW <= NEW_ROW;
OLD_COLUMN <= NEW_COLUMN;
NEW_ROW <= "1111";
NEW_COLUMN <= "111";
end if;
end if;
end process;
-- connect intermediate signal to output port
KEY <= I_KEY;
------------------------------------------------------------------
-- This process stores the last 4 keys pressed. The A_FSM block
-- detects the new key value and triggers the shift pulse to shift
-- in the new key value.
------------------------------------------------------------------
KEY_STORE: process (CLK, RESET)
begin
if RESET = '1' then
I_KEY_BUFFER_0 <= "0000";
I_KEY_BUFFER_1 <= "0000";
I_KEY_BUFFER_2 <= "0000";
I_KEY_BUFFER_3 <= "0000";
elsif CLK'event and CLK = '1' then
if SHIFT = '1' then
I_KEY_BUFFER_3 <= I_KEY_BUFFER_2;
I_KEY_BUFFER_2 <= I_KEY_BUFFER_1;
I_KEY_BUFFER_1 <= I_KEY_BUFFER_0;
I_KEY_BUFFER_0 <= I_KEY;
end if;
end if;
end process;
-- connect intermediate signals to output ports
KEY_BUFFER_0 <= I_KEY_BUFFER_0;
KEY_BUFFER_1 <= I_KEY_BUFFER_1;
KEY_BUFFER_2 <= I_KEY_BUFFER_2;
KEY_BUFFER_3 <= I_KEY_BUFFER_3;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -