背景

此篇文章是4x4矩阵键盘的衍生品。

4x4的矩阵键盘一共16个按键,每个按键对应相应的键值,分别为0~15。每按一个键,对应的键值并联到4个LED灯上,以二进制的形式表示(比如键值5,二进制为'b0101,对应的LED灯亮灭情况为:亮灭亮灭),同时也并联到数码管上,通过数码管显示出目前对应的键值。

然而,一个数码管足够显示0~F(即0到15)这16个键值,如果想完完全全转换成十进制来显示,即键值10显示为10而非a,键值11显示为11而非b,那该如何操作呢?

以上即为不安分守己的瞎折腾背景。

开始

之前,写过一篇关于小梅哥74HC595驱动设计的思考,该驱动可充分利用两片级联的74HC595芯片,将16位串行数据转换为16位并行数据。实际应用中,由于开发板上有8个数码管;每个数码管又有8个段,正好16位数据。驱动将16位并行数据data[15:0]输入,输出串行的16位数据ds,并利用两片级联芯片将16位数据ds再次转为并行数据输出,以此驱动数码管,并显示相应数据。选择对应的数码管(以sel[7:0]信号表示),数码管上对应需要显示的段(以seg[7:0]信号表示)。

目前74HC595驱动已经写好,只等数码管的位选和段选数据输入。产生16位数据的verilog文件以梅哥的hex8.v文件为参考,并作些许修改。其中有一两个小技巧一同分享。

分析

大于等于10的数据,其二进制编码有以下特点:

  1. 最高位dis_data[3]永远为1;
  2. dis_data[2]dis_data[1]取逻辑或,其值永远为1;

虽然键值8和9的最高位也为1,但是其dis_data[2]dis_data[1]为0,两者相或,值为0.

以上,足以利用该特点进行两个数码管显示0~15,即令
wire oct = dis_data[3] && (dis_data[2] || dis_data[1]) ;(英文oct即为十进制的意思)
oct == 1,即键值大于等于10,选择两个数码管进行显示,并将第二个数码管永远置为1;
oct == 0,既键值小于10,只需选择一个数码管进行显示。

产生位选sel[7:0]和段选seg[7:0]的代码如下:

/*=============================================================================
#     FileName: hex8.v
#         Desc: copy from 小梅哥
#       Author: 小梅哥
#        Email:
#     HomePage:
#      Version: 0.0.1
#   LastChange: 2019-11-30 16:49:52
#      History:
=============================================================================*/
module hex8(clk_50M ,rstn    ,en_hex8 ,dis_data,sel     ,seg
);input        clk_50M    ;
input        rstn       ;
input        en_hex8    ;
input [3:0]     dis_data   ;output     [7:0] sel    ;
output reg [7:0] seg    ;reg [15:0] cnt   ;
reg        clk_1K;
reg [7 :0] select;  //定义一个中间寄存器,数码管位选信号sel用来调用,详见代码第74行parameter CNT_NUM = 16'd25_000;wire oct = (dis_data[3] && (dis_data[2] || dis_data[1]));//divide clk_50M to clk_1K
//用频率为1K的时钟进行8个数码管的扫描
always @ (posedge clk_50M or negedge rstn) beginif (!rstn)cnt <= 16'h0;else if (!en_hex8)cnt <= 16'h0;else beginif (cnt == CNT_NUM/2 - 1)cnt <= 16'h0;elsecnt <= cnt + 1'b1;end
endalways @ (posedge clk_50M or negedge rstn) beginif (!rstn)clk_1K <= 1'b0;else if (cnt == CNT_NUM/2 - 1)clk_1K <= ~clk_1K;elseclk_1K <= clk_1K;
end//gate control clk
//scanning the hex
always @ (posedge clk_1K or negedge rstn) beginif (!rstn)select <= 8'b0000_0001;else if (oct) beginif (select == 8'b0000_0010)  //只选择末端两个数码管select <= 8'b0000_0001;elseselect <= select << 1;endelseselect <= 8'b0000_0001;
endassign sel = (en_hex8 ? (oct ? select : 8'b0000_0001) : 8'b0);reg [3:0] data_tmp;
always @ (*) beginif (oct) begin //如果键值大于等于10case (sel)8'b0000_0001 : data_tmp = dis_data[2 : 0];8'b0000_0010 : data_tmp = dis_data[3    ];default      : data_tmp = 4'b0           ;endcaseendelse  //如果键值小于10data_tmp = dis_data[3 : 0];
endalways @ (*) beginif (oct) begincase (data_tmp)3'd1 : seg = 8'b1111_1001;  //第二个数码管显示13'd2 : seg = 8'b1100_0000;  //第一个数码管显示其他数3'd3 : seg = 8'b1111_1001;3'd4 : seg = 8'b1010_0100;3'd5 : seg = 8'b1011_0000;3'd6 : seg = 8'b1001_1001;3'd7 : seg = 8'b1001_0010;default : seg = 8'b1111_1111;endcaseendelsecase(data_tmp)4'd0 : seg = 8'b1100_0000;4'd1 : seg = 8'b1111_1001;4'd2 : seg = 8'b1010_0100;4'd3 : seg = 8'b1011_0000;4'd4 : seg = 8'b1001_1001;4'd5 : seg = 8'b1001_0010;4'd6 : seg = 8'b1000_0010;4'd7 : seg = 8'b1111_1000;4'd8 : seg = 8'b1000_0000;4'd9 : seg = 8'b1001_0000;default : seg = 8'b1111_1111;endcase
end
endmodule

比较巧妙的是,当键值大于等于10,将dis_data拆分成dis_data[3]dis_data[2:0];由于dis_data[3] == 1'b1,且

  1. 当键值为10,dis_data[2:0] == 2
  2. 当键值为11,dis_data[2:0] == 3
  3. 当键值为12,dis_data[2:0] == 4

  4. 而在case语句中,最高位dis_data[3]的取值正好不与后三位dis_data[2:0]的取值重合,故当oct == 1时,可直接在case语句中判断整个dis_data[3:0]的情况,并将其在数码管上显示出来。

将该文件的输出sel[7:0]seg[7:0],以{seg[7:0], sel[7:0]}的顺序位拼接并连上74HC595驱动上的data端口,调用ISSP可实现两个数码管显示16位数据。两文件调用方式如下:

module hex_top(clk     ,rstn    ,ds      ,shcp    ,stcp
);input       clk     ;
input       rstn    ;output  ds    ;
output  shcp  ;
output  stcp  ;wire [3:0] dis_data;
wire [7:0] sel     ;
wire [7:0] seg     ;hex_data_ISSP U_hex_data(.probe  (        ),.source (dis_data)
);hex8 U_hex8(.clk_50M    (clk     ),.rstn       (rstn    ),.en_hex8    (1'b1    ),  .dis_data   (dis_data),.sel        (sel     ),.seg        (seg     )
);HC595_driver U0_HC595_driver(.clk    (clk        ),.rstn   (rstn       ),.data   ({seg, sel} ),.en     (1'b1       ),.ds     (ds         ),.shcp   (shcp       ),.stcp   (stcp       )
);endmodule

实际效果

由于此文作为矩阵键盘的一个衍生品,故实际验证的过程中本人将矩阵键盘与数码管显示相结合,当然调用ISSP只是为了降低此文写作难度(矩阵键盘还没想好怎么写–!),视频如下:

FPGA两段数码管显示0~15的数字

两个数码管显示16位数相关推荐

  1. c语言静态两个数码管显示0-99,按键控制计数,用两个数码管显示0到99。十位数为0的时候,显示为空白...

    //用两个数码管显示0到99.十位数为0的时候,显示为空白. //用两个按键控制数值的加减,按一次K1数字加1,按一次K2数字减1,数值的范围是从0到99. //再用一个接近开关控制数字的减小,接近开 ...

  2. 两位数码管秒表c语言,两位数码管显示计时器.doc

    两位数码管显示计时器 一.题目 用定时0的方式1实现数码管两位59S循环计时(计时器) 二.思路方案 本实验利用单片机的定时器/计数器定时和计数的原理,通过proteus 仿真软件来实现模拟实现.模拟 ...

  3. FPGA初探(五)之两位数码管显示

    两位数码管显示 目标: 共阳极数码管实现动态显示 实现过程规划(功能分解,分步实现): 取得两位数0~99, 第一步,分成个位十位, 第二步,将个位十位转换为数码管编码, 第三步,数码管显示模块: 1 ...

  4. 两位数码管30秒倒计时c语言,基于51单片机共阴两位数码管显示倒计时

    <基于51单片机共阴两位数码管显示倒计时>由会员分享,可在线阅读,更多相关<基于51单片机共阴两位数码管显示倒计时(2页珍藏版)>请在人人文库网上搜索. 1.基于51单片机共阴 ...

  5. 51单片机矩阵按键详解,两位数码管显示(普中HC6800ESV2.0)

    一.简述 本人是一名在校生,这个学期刚好在学单片机,自己也挺有兴趣,前面在写数码管.时钟啥的程序时都没什么大问题,但是做到矩阵按键时碰到了一些问题,不过已经解决,下面我会把碰到的问题和解决方法都写出来 ...

  6. 使用定时器的中断方式。具体功能描述如下:使用定时器控制三位数码管显示时间,也可以轻易改为两位数码管显示时间

    #include <REGX52.H> unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0 ...

  7. 两位数码管显示学号练习程序和图_数码管的原理与作用

    今天来说一下数码管,数码管在电路中应用的也是比较多的,在生活中随处可见,比如电饭煲,电子钟,洗衣机,等各种家用电器都会用到数码管,既然知道了它的用处,那么就来说说他的原理 数码管的原理其实非常简单,它 ...

  8. c语言两位数码管程序,单片机制作—两位数码管显示 c语言 汇编程序+电路图

    程序清单(汇编): ;2011 04 05 D:\DPJ\数码管段显\数码管段显2.asm S0 BIT P3.7 ORG 00H AJMP MAIN ORG 0BH AJMP T0INT ORG 3 ...

  9. 交通灯keil程序加2位数码管_51单片机红绿灯两个数码管显示实验报告

    实验操作方法和步骤 1.熟悉keil C51基本操作 1.1熟悉keil C51命令窗口以及工作空间 2.打开Keil C51编译器: ⑴创建项目:Project------New uVision P ...

最新文章

  1. 从数仓到数据中台,谈技术选型最优解
  2. 怎么把数字替换成空格_Excel中带单位后缀的数字如何计算?
  3. 全国大学智能车竞赛完全模型组中的赛道标志
  4. torch维度获取数据详解
  5. Java 403 forbidden错误解决
  6. 嵌入式linux组件,嵌入式Linux系统的几大组件!
  7. 关于java AudioInputStream播放短音频没声音的问题
  8. Ubuntu搜狗输入法不能显示问题
  9. Python绘制一箭穿双心 动画代码
  10. ybc_xxx类模块应用1-ybc_speech(第一片)
  11. 堂食扫码点餐的小程序设计开发
  12. oracle会话占用pga异常,OLTP,单个session占pga大于2G,有见过的没?
  13. 【CSS解决页面高度塌陷问题】
  14. SAP FI-CO应收应付重分类
  15. 谷粒商城-分布式事务
  16. 关于微信豆苹果(IOS)用户1比10充值方法
  17. linux gdm错误,gdm 系统出错且无法恢复
  18. python下载m3u8视频_使用python 下载m3u8格式视频,并使用ffmpeg 合成视频
  19. 讯闪Linux虚拟磁盘双网卡绑定方法
  20. Java数组分隔成子数组

热门文章

  1. vscode 添加用户代码片段(快速生成 vue 模板)
  2. idea连接数据库快速生成pojo类
  3. Java实现emf转jpg png 图片转换
  4. c语言字母意义,C语言 字符串前加L的意义 如:L“A”
  5. Unable to add window -- token android.view.ViewRootImpl$W@e3124a is not vali
  6. HTML+CSS期末大作业:美妆网站设计——化妆品企业(20页) 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码
  7. TEC-2机微程序设计实验
  8. 黑色笼罩中国联通:半年流失近千万用户 4G发展停滞不前---OFweek
  9. 开源Jabber(XMPP) IM服务器介绍
  10. LayaBox热更新问题