设为首页收藏本站淘宝杂货铺

从F到0 - From F to 0

 找回密码
 注册已关闭
搜索
查看: 1210|回复: 6
收起左侧

Quartus Verilog HDL/FPGA 驱动4x4矩阵键盘 多按键识别/鬼键处理 4位动态数码管显示

[复制链接]
发表于 2022-2-11 21:04:41 | 显示全部楼层 |阅读模式
main.png
  1. `define fosc 50000000        //晶振频率
  2. `define scan 1000000        //矩阵键盘扫描频率

  3. module display4(                                //4位数码管模块
  4.         input clk,                                        //有源晶振输入
  5.         input [15:0] hex,                        //数码管显示的16进制字符
  6.         output [7:0] seg_code,        //数码管段码 8位        A~DP
  7.         output [3:0] bit_code        //数码管位码 4位 1:千位 2:百位 4:十位 8:个位
  8. );

  9. function [7:0] display;                        //16进制数码管段码查询
  10.         input [3:0] hex;
  11.         begin
  12.         case(hex)
  13.                 4'h0:display = 8'h3F;
  14.                 4'h1:display = 8'h06;
  15.                 4'h2:display = 8'h5B;
  16.                 4'h3:display = 8'h4F;
  17.                 4'h4:display = 8'h66;
  18.                 4'h5:display = 8'h6D;
  19.                 4'h6:display = 8'h7D;
  20.                 4'h7:display = 8'h07;
  21.                 4'h8:display = 8'h7F;
  22.                 4'h9:display = 8'h6F;
  23.                 4'hA:display = 8'h77;
  24.                 4'hB:display = 8'h7C;
  25.                 4'hC:display = 8'h39;
  26.                 4'hD:display = 8'h5E;
  27.                 4'hE:display = 8'h79;
  28.                 4'hF:display = 8'h71;       
  29.         endcase
  30.         end
  31. endfunction

  32. integer i;
  33. reg [1:0] j;
  34. reg [7:0] k;
  35. reg [3:0] l;
  36. assign seg_code = k;
  37. assign bit_code = l;

  38. always @(posedge clk) begin
  39.         i = i + 1;
  40.         if(i == `fosc/1000) begin
  41.                 i = 0;
  42.                         j <= j + 1;
  43.                         /*
  44.                         共阴或共阳 如果显示不正确
  45.                         可将 seg_code 或 bit_code 前的 ~号去除
  46.                         并检查A~DP的Pin是否设置颠倒
  47.                         */
  48.                         case(j)
  49.                                 0:k <= ~display(hex[15:12]);
  50.                                 1:k <= ~display(hex[11:8]);
  51.                                 2:k <= ~display(hex[7:4]);
  52.                                 3:k <= ~display(hex[3:0]);
  53.                         endcase
  54.                         l <= ~(1 << j);
  55.         end
  56. end
  57. endmodule

  58. module keyboard4x4_ghost(                //4x4矩阵键盘 鬼键处理模块
  59.         input [15:0] key,                                //16位按键 按下1 松开0
  60.         output ghost                                        //按键组合是否发生鬼键 (按键冲突)
  61. );

  62. reg [3:0] i;
  63. reg [23:0] j;
  64. reg k;
  65. assign ghost = k;
  66. always @(*) begin
  67.         i = 0;
  68.         k = 0;
  69.         repeat(16) begin
  70.                 case(i)
  71.                         4'h0:j = 24'h12348C;                //0的X方向有:1,2,3,Y方向有:4,8,C
  72.                         4'h1:j = 24'h02359D;                //0与X:(1或2或3) 与 Y:(4或8或C)
  73.                         4'h2:j = 24'h0136AE;                //以上3个按键同时按下即为鬼键,以此类推
  74.                         4'h3:j = 24'h0127BF;                //当按键0,3,C按下后,按键F的回路被导通
  75.                         4'h4:j = 24'h56708C;                //此表格严禁修改,否则会出错
  76.                         4'h5:j = 24'h46719D;
  77.                         4'h6:j = 24'h4572AE;
  78.                         4'h7:j = 24'h4563BF;
  79.                         4'h8:j = 24'h9AB04C;
  80.                         4'h9:j = 24'h8AB15D;
  81.                         4'hA:j = 24'h89B26E;
  82.                         4'hB:j = 24'h89A37F;
  83.                         4'hC:j = 24'hDEF048;
  84.                         4'hD:j = 24'hCEF159;
  85.                         4'hE:j = 24'hCDF26A;
  86.                         4'hF:j = 24'hCDE37B;
  87.                 endcase
  88.                 k = k | (key[i] && (
  89.                         key[j[23:20]] |
  90.                         key[j[19:16]] |
  91.                         key[j[15:12]]
  92.                 ) && (
  93.                         key[j[11:08]] |
  94.                         key[j[07:04]] |
  95.                         key[j[03:00]]
  96.                 ));
  97.                 i = i + 1;
  98.         end
  99. end
  100. endmodule

  101. module keyboard4x4(                        //4x4矩阵键盘模块
  102.         input clk,                                        //有源晶振输入
  103.         input k0,                                        //矩阵键盘第1脚
  104.         input k1,                                        //k0~k3必须配置为弱上拉
  105.         input k2,                                        //否则会受到干扰出错
  106.         input k3,
  107.         output k4,                                        //k4~k7只允许输出0和高阻态
  108.         output k5,                                        //否则多按键同时按下可能会短路
  109.         output k6,
  110.         output k7,                                        //第8脚
  111.         output [15:0] key                        //16位对应16个按键 矩阵键盘按下哪些按键 按下置1 松开清0 发生鬼键全部置1 (已消抖)
  112. );

  113. wire [3:0] ki;
  114. assign ki[0] = k0;
  115. assign ki[1] = k1;
  116. assign ki[2] = k2;
  117. assign ki[3] = k3;
  118. reg [3:0] ko;
  119. assign k4 = ko[0] ? 1'bz : 1'b0;
  120. assign k5 = ko[1] ? 1'bz : 1'b0;
  121. assign k6 = ko[2] ? 1'bz : 1'b0;
  122. assign k7 = ko[3] ? 1'bz : 1'b0;
  123. reg [1:0] i;
  124. reg [1:0] j;
  125. integer k;
  126. reg [15:0] l;
  127. reg [15:0] m;

  128. integer n;
  129. reg [3:0] o;
  130. reg [15:0] p;
  131. reg [15:0] q;                                               
  132. reg [15:0] r;
  133. reg [4:0] s [15:0];
  134. wire t;
  135. assign key = r;

  136. keyboard4x4_ghost keyboard4x4_ghost(
  137.         .key(q),
  138.         .ghost(t)
  139. );

  140. always @(posedge clk) begin                //矩阵键盘按键扫描
  141.         k = k + 1;
  142.         if(k >= `fosc/`scan) begin
  143.                 k = 0;
  144.                 ko = ~(1 << i);
  145.                 i = i + 1;
  146.                 j = 0;
  147.                 repeat(4) begin
  148.                         if(!ki[j]) begin
  149.                                 l[{i^1,~j}] = 1;
  150.                         end
  151.                         j = j + 1;
  152.                 end
  153.                 if(i == 0) begin
  154.                         m = l;
  155.                         l = 0;
  156.                 end
  157.         end
  158. end

  159. always @(posedge clk) begin                //矩阵键盘按键消抖 (去抖)
  160.         n = n + 1;
  161.         if(n >= `fosc/1000) begin
  162.                 n = 0;
  163.                 repeat(16) begin
  164.                         if(m[o]) begin
  165.                                 if(!(&s[o])) begin
  166.                                         s[o] = s[o] + 1;
  167.                                 end
  168.                         end else begin
  169.                                 s[o] = 0;
  170.                         end
  171.                         p[o] = &s[o];
  172.                         o = o + 1;
  173.                         if(o == 0) begin
  174.                                 q = p;
  175.                                 p = 0;
  176.                                 r = t ? 16'hFFFF : q;
  177.                         end
  178.                 end
  179.         end
  180. end
  181. endmodule

  182. /*
  183. 矩阵键盘按键与代码:
  184. 1 2 3 A | 0 1 2 3 | 0001 0002 0004 0008
  185. 4 5 6 B | 4 5 6 7 | 0010 0020 0040 0080
  186. 7 8 9 C | 8 9 A B | 0100 0200 0400 0800
  187. * 0 # D | C D E F | 1000 2000 4000 8000
  188. */

  189. module main(
  190.         input clk,                                        //有源晶振输入
  191.         //接矩阵键盘
  192.         input k0,                                       
  193.         input k1,
  194.         input k2,                                       
  195.         input k3,
  196.         output k4,                                       
  197.         output k5,
  198.         output k6,
  199.         output k7,
  200.         //接数码管
  201.         output [7:0] seg_code,                //数码管段码 8位        A~DP
  202.         output [3:0] bit_code                //数码管位码 4位 1:千位 2:百位 4:十位 8:个位
  203. );

  204. wire [15:0] hex;
  205. wire [15:0] key;
  206. display4 display4(
  207.         .clk(clk),
  208.         .hex(hex),
  209.         .seg_code(seg_code),
  210.         .bit_code(bit_code)
  211. );

  212. keyboard4x4 keyboard4x4(
  213.         .clk(clk),
  214.         .k0(k0),
  215.         .k1(k1),
  216.         .k2(k2),
  217.         .k3(k3),
  218.         .k4(k4),
  219.         .k5(k5),
  220.         .k6(k6),
  221.         .k7(k7),
  222.         .key(key),
  223. );
  224. assign hex = key;
  225. endmodule
复制代码

相关帖子

发表于 2022-2-18 11:45:05 | 显示全部楼层

我也是
发表于 2022-3-29 19:13:30 | 显示全部楼层
发表于 2022-4-4 14:00:38 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册已关闭

本版积分规则

QQ|手机版|Archiver|从F到0 ( 蒙ICP备17002595号-1 )
蒙公网安备15010402000325号

腾讯云安全认证

GMT+8, 2024-3-29 03:39 , Processed in 0.606035 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表