• 正文
  • 相关推荐
申请入驻 产业图谱

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

10/24 11:31
703
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

·名称: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;


代码获取:

 

【来源:www.hdlcode.com

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录