4×4矩阵键盘控制实验
一、实验内容摘要
设计一个4×4键盘接口控制器,在QuartusII软件上实现基设计,将其与开发板连接,实
现电路功能。当按下某一键时,4位LED上显示对应的键值,以二进制代码形式从0至F显示。
二、实验源代码
LIBRARY ieee;
USE ieee.std_logic_1164.ALL; USE ieee.std_logic_unsigned.ALL; ENTITY DEBOUNCING IS PORT( clk, key:IN STD_LOGIC ; clr: IN STD_LOGIC; dly_out, dif_out: OUT STD_LOGIC); END DEBOUNCING;
ARCHITECTURE a OF DEBOUNCING IS SIGNAL sample,dly,diff: STD_LOGIC; BEGIN
free_counter:block signal QQ:std_logic_vector(4 downto 0); signal d0:std_logic; begin process (CLR,clk) begin if clr='0' then d0<='0'; QQ<=(OTHERS=>'0'); ELSif clk'event and clk='1' then d0<=QQ(4); --QQ的最高位同时作为d0信号,即d0的周期为2的5次方个clk. QQ<=QQ+1; end if; end process;
sample<=not(QQ(4) and (not d0));--当d0为0,QQ(4)为1时,sample产生采样脉冲,低电平时间为1个clk
end block free_counter;
debunce:block signal d0,d1,s,r:std_logic; begin process(clk,clr) begin if clr='0' then dly<='0'; elsif rising_edge(clk) then if sample='1' then d1<=d0; d0<=key; s<=d0 and d1; r<=not d0 and not d1; if s<='0' and r<='0' then
dly<=dly; elsif s<='0' and r<='1' then dly<='0'; elsif s<='1' and r<='0' then dly<='1'; else dly<='0'; end if; end if; end if; end process; dly_out<=dly;
end block debunce;
differential:block signal d1,d0:std_logic; begin process(clk,clr) begin if clr='0' then d0<='0'; d1<='0'; elsif rising_edge(clk) then d1<=d0; d0<=dly; end if; diff<=d0 and not d1; end process; dif_out<=diff; end block differential; END a;
--****************************************************************** --* 4x4标准键盘板读取并点亮实验箱底板上的L1-L4 --* Filename: keyboard4_4
--* 扫描键盘,译码并点亮实验箱底板上的L1-L4 --* 已加入去抖程序
--******************************************************************
library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity keyboard4_4 is port(
rst : in std_logic; clk_in : in std_logic;
keyin : in std_logic_vector(3 downto 0); scan : out std_logic_vector(3 downto 0); leds : out std_logic_vector(3 downto 0); state : out std_logic; M : out std_logic_vector(3 downto 0) );
end keyboard4_4;
architecture keyboard4_4_arch of keyboard4_4 is --
--********************************************* component debouncing port( key : IN STD_LOGIC ; clk,clr : IN STD_LOGIC ; dly_out : OUT STD_LOGIC ) ; end component ;
--********************************************* --
signal clkfrq : std_logic;
signal cntscn : std_logic_vector(1 downto 0); signal scnlin : std_logic_vector(3 downto 0); signal cntfrq : std_logic_vector(14 downto 0); signal lednum : std_logic_vector(7 downto 0); signal key_tmp : std_logic_vector(3 downto 0); signal clk : std_logic; signal cntfrq1 : std_logic_vector(5 downto 0); begin M <= \ --键盘功能选择 scan <= not scnlin;
lednum <= scnlin & (not key_tmp); -- key_tmp <= keyin;
--debounuing ckt debounuing : block begin U1: debouncing PORT MAP ( KEY => keyin(0) , DLY_OUT => key_tmp(0) , clr=>rst, clk => CLK ); U2: debouncing PORT MAP ( KEY => keyin(1) , dly_out => key_tmp(1) , clr=>rst, clk => CLK ); U3: debouncing PORT MAP ( key => keyin(2) , dly_out => key_tmp(2) , clr=>rst, clk => CLK ); U4: debouncing PORT MAP ( key => keyin(3) , dly_out => key_tmp(3) , clr=>rst, clk => CLK ); END block debounuing ;
--
--****************************************************** --
process(rst,clk_in) -- 晶振为40MHz,进行40000分频产生去抖时钟(1000Hz) begin
if rst = '0' then
cntfrq <= (others => '0'); elsif rising_edge(clk_in) then
if (cntfrq = \ key_tmp=\key_tmp=\
--if (cntfrq = \ --if cntfrq = \ cntfrq <= (others => '0'); clk <= not clk;--去抖时钟 else
cntfrq <= cntfrq + 1; end if; end if; end process; process(rst,clk) --去抖时钟,50分频,形成扫描时钟 begin if rst = '0' then clkfrq <= '0'; cntfrq1 <= (others => '0'); elsif rising_edge(clk) then if cntfrq1 = \ cntfrq1 <= (others => '0'); clkfrq <= not clkfrq; else cntfrq1 <= cntfrq1 + 1; end if; end if; end process;
process(rst,clkfrq) -- 根据扫描时钟产生扫描线 begin
if rst = '0' then
cntscn <= \
elsif rising_edge(clkfrq) then if cntscn = \ cntscn <= \ else
cntscn <= cntscn+1; end if;
case cntscn is
when \ when \ when \ when \ when others => null; end case; end if;
end process;
process(rst, clkfrq) -- 根据按键点亮相应的leds begin
if(rst = '0' ) then leds <= \
elsif clkfrq'event and clkfrq = '0' then case lednum is
when \ leds <= \--1 when \ leds <= \--2 when \ leds <= \--3 when \ leds <= \ when \ leds <= \--4 when \ leds <= \ when \ leds <= \--6 when \ leds <= \--B when \ leds <= \--7 when \ leds <= \--8 when \ leds <= \--9 when \ leds <= \--C when \ leds <= \--* when \ leds <= \--0 when \ leds <= \ when \
leds <= \ when others => null; end case; end if; end process; process(rst,key_tmp) begin if(rst = '0' ) then state <= '1'; elsif (key_tmp=\then state <= '0';