• 方案介绍
  • 相关推荐
申请入驻 产业图谱

4x4 矩阵键盘输入与四位数码管显示 VHDL 语言 Quartus II软件

11小时前
250
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

·名称:4x4矩阵键盘到数码管 · VHDL · Quartus II

·软件:Quartus II

·语言:VHDL

代码功能(概述)

本设计实现对 4×4 矩阵键盘的行列扫描与按键识别,将数字键 0~9 的按下事件转换为四个 BCD 字(共 16 位),并通过 7 段数码管(4 位)进行实时显示。核心流程包括:键盘扫描与去抖(边沿检测)、按键值编码、数据移位拼接(高位左移,低 4 位写入新 BCD)、以及七段码译码输出。整体结构清晰、模块化强,便于移植与扩展。

代码实现思路(设计要点)

·键盘扫描:key_4x4 模块以扫描列(H_col)—读取行(L_row)的方式逐行判定,内部使用状态机依次驱动列线并采样行线,定位按键矩阵坐标,输出独热码 key_number(15:0)

·上升沿检测:key_input 对 key_number 的每一位进行双拍寄存,生成 A~F 与 0~9 的上升沿脉冲。顶层仅使用 0~9 脉冲。

·数据拼接:data_ctrl 接收 key_0~key_9 的上升沿,每次按键将 16 位寄存器整体左移 4 位,并在低 4 位写入对应 BCD(0000~1001)。复位有效时清零。

·显示译码:HEX 将 16 位数据按 4 位切片,交由 4 个 LED7S 子模块分别译码为七段显示;LED7S 采用查表 case 语句覆盖 0~F 的七段码。

 

 

 

 

 

简化框图:

L_row → key_4x4 → key_input →(key_0..key_9 上升沿)→ data_ctrl → data[15:0] → HEX → HEX3..HEX0
               ↑           ↓                                      ↑
            H_col(列驱动)  复位/时钟                         LED7S×4(七段译码)

代码结构(模块说明)

·key_seg(顶层):连接键盘输入、数据拼接与显示模块,形成完整数据通路并对外暴露接口。

·key_input:对 key_4x4 的独热键值进行双拍,同步并产生 0~F 按键的上升沿脉冲。

·key_4x4:实现 4×4 键盘的行列扫描状态机,将按键位置编码为 16 位独热键值。

·data_ctrl:接收数字键上升沿事件,按次序将 BCD 值左移拼接到 16 位数据寄存器中。

·HEX:将 16 位数据按 4 位切片,驱动 4 组七段显示接口 HEX3..HEX0

·LED7S:0~F 的七段码译码查表,输出段选信号。

演示视频:

 

1、工程文件

 

2、程序文件

 

 

3、程序编译

 

4、RTL图

 

5、仿真图

整体仿真图

 

矩阵按键输入模块

 

 

数据控制模块

数码管显示模块

部分代码展示:

 

 

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   --矩阵键盘
ENTITY key_4x4 IS
   PORT (
      clk_100KHz  : IN STD_LOGIC;
      reset       : IN STD_LOGIC;
      L_row       : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--行 
      H_col       : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--列 
      key_number  : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)--按键键值
   );
END key_4x4;
ARCHITECTURE trans OF key_4x4 IS
   
   CONSTANT s_L_all        : INTEGER := 0;
   CONSTANT s_L_row1       : INTEGER := 1;
   CONSTANT s_L_row2       : INTEGER := 2;
   CONSTANT s_L_row3       : INTEGER := 3;
   CONSTANT s_L_row4       : INTEGER := 4;
   CONSTANT s_LH           : INTEGER := 5;
   
   SIGNAL state            : INTEGER:= s_L_all;--状态标志 
   SIGNAL key_flag         : STD_LOGIC := '0';--按键标志位 
   SIGNAL H_col_reg        : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";--寄存扫描列值 
   SIGNAL L_row_reg        : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";--寄存扫描行值 
   SIGNAL H_and_L : STD_LOGIC_VECTOR(7 DOWNTO 0);
   
   -- Declare intermediate signals for referenced outputs
   SIGNAL H_col_sig      : STD_LOGIC_VECTOR(3 DOWNTO 0);
   SIGNAL key_number_sig : STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
   -- Drive referenced outputs
   H_col <= H_col_sig;
   key_number <= key_number_sig;
--************************************************************************ 
--逐行扫描原理 
--************************************************************************/    
   PROCESS (clk_100KHz, reset)
   BEGIN
      IF ((NOT(reset)) = '1') THEN
         H_col_sig <= "0000";
         H_col_reg <= "0000";
         L_row_reg <= "0000";
         state <= s_L_all;
      ELSIF (clk_100KHz'EVENT AND clk_100KHz = '1') THEN
         CASE state IS
            WHEN s_L_all =>
               H_col_sig(3 DOWNTO 0) <= "0000";
               key_flag <= '0';
               IF (L_row(3 DOWNTO 0) /= "1111") THEN
                  state <= s_L_row1;
                  H_col_sig(3 DOWNTO 0) <= "0111";--有键按下,扫描第一行 
               ELSE
                  state <= s_L_all;
               END IF;
            WHEN s_L_row1 =>
               IF (L_row(3 DOWNTO 0) /= "1111") THEN
                  state <= s_LH;--判断是否是第一行 
               ELSE
                  state <= s_L_row2;
                  H_col_sig(3 DOWNTO 0) <= "1011"; --扫描第二行 
               END IF;
            WHEN s_L_row2 =>
               IF (L_row(3 DOWNTO 0) /= "1111") THEN
                  state <= s_LH;--判断是否是第二行
               ELSE
                  state <= s_L_row3;
                  H_col_sig(3 DOWNTO 0) <= "1101";--扫描第三行 
               END IF;
            WHEN s_L_row3 =>
               IF (L_row(3 DOWNTO 0) /= "1111") THEN
                  state <= s_LH;--判断是否是第三行 
               ELSE
                  state <= s_L_row4;
                  H_col_sig(3 DOWNTO 0) <= "1110";--扫描第四行 
               END IF;
            WHEN s_L_row4 =>
               IF (L_row(3 DOWNTO 0) /= "1111") THEN
                  state <= s_LH;--判断是否是第四行 
               ELSE
                  state <= s_L_all;
               END IF;
            
            WHEN s_LH =>
               IF (L_row(3 DOWNTO 0) /= "1111") THEN
                  H_col_reg <= H_col_sig;--保存扫描列值 
                  L_row_reg <= L_row; --保存扫描行值 
                  state <= s_LH;
                  key_flag <= '1';--有键按下 
               ELSE
                  state <= s_L_all;
               END IF;

 

 

代码获取(付费下载):

 

 

 

 

相关推荐