⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyscan.vhd

📁 Workshop vhdl code from Esperan
💻 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 + -