明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 4456|回复: 0

【每周FPGA案例】至简设计系列_7段数码管显示

[复制链接]
发表于 2020-8-11 21:25:24 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
【上板现象】
7段数码管显示在MP801的上板现象



7段数码管显示在点拨开发板的上板现象



7段数码管显示在实验箱的上板现象



【设计教程】

至简设计系列_7段数码管显示

--作者:肖肖肖

本文为明德扬原创及录用文章,转载请注明出处

1.1 总体设计1.1.1 概述
LED数码管以发光二极管作为发光单元,颜色有单红,黄,蓝,绿,白,黄绿等效果,并且可以构造成“8”字形。数码管根据LED的接法不同分为共阴和共阳两类,它们的发光原理是一样的,只是它们的电源极性不同而已。

数码管可以通过驱动电路来驱动内部的各个段码,从而显示出需要的数字。根据数码管驱动方式的不同,可以将其分为静态式和动态式两类。

1.1.2 设计目标
完成数码管的显示,具体功能要求如下:

1.       间隔1s切换数码管位选,做到数码管从左到右流动显示的效果;
2.       数码管显示的数值从0开始,每切换一位位选数值加一;

1.1.3信号列表
  
信号名
  
I/O
位宽
定义
  
clk
  
I
1
系统工作时钟 50M
  
rst_n
  
I
1
系统复位信号,低电平有效
  
segment
  
O
8
8位数码管段选信号。
  
由低到高,分别表示数码管的a,b,c,d,e,f,g,dp,低电平时,点亮对应段位。
  
seg_sel
  
O
8
8位数码管位选信号,低电平时,对应位置数码管点亮。



1.1.4
设计思路


Ø  数码管显示原理
数码管的8个显示字段”a、b、c、d、e、f、g、h”对应显示面板的位置如下图所示。
1.png

数码管显示数字0到9对应的gfedcba值如下表所示。

表5- 1 数码管显示数字与字段值的对应关系
  
显示
  
数字
  
共阳gfedcba
  
2进制
共阳gfedcba
  
16进制
共阴gfedcba
  
2进制
共阴gfedcba
  
16进制
  
0
  
7’b1000000
7’h40
7’b 0111111
7’h3f
  
1
  
7’b 1111001
7’h79
7’b 0000110
7’h06
  
2
  
7’b 0100100
7’h42
7’b 1011011
7’h5b
  
3
  
7’b 0110000
7’h30
7’b 1001111
7’h4f
  
4
  
7’b 0011001
7’h19
7’b 1100110
7’h66
  
5
  
7’b 0010010
7’h12
7’b 1101101
7’h6d
  
6
  
7’b 0000010
7’h02
7’b 1111101
7’h7d
  
7
  
7’b 1111000
7’h78
7’b 0000111
7’h07
  
8
  
7’b 0000000
7’h00
7’b 1111111
7’h7f
  
9
  
7’b 0010000
7’h10
7’b 1101111
7’h6f

数码管静态驱动是指每个数码管的每一个段码都通过一个I/O端口进行驱动,或使用如BCD码二-十进制译码器译码进行驱动,也称直流驱动。静态驱动编程简单,显示亮度高,但占用的I/O端口多,这里不使用这种方法。

数码管动态驱动是将所有数码管的8个显示字段"a、b、c、d、e、f、g、h"的同名端连接在一起,此外每个数码管的公共极COM需增加由各自独立I/O线控制的位选通控制电路。当要输出某一字形码时,所有数码管都会接收到相同的字形码,但究竟是哪个数码管会显示出字形取决于单片机对位选通COM端电路的控制。只需将显示数码管的选通控制打开,该位就会显示出字形,而没有选通的数码管并不会点亮。数码管特定的发光二极管段加上电压后,这些特定的段就会发亮,并且当每位元数码管的点亮时间为1~20ms,由于人的视觉暂留现象及发光二极体的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示资料,不会有闪烁感,使得动态显示的效果和静态显示是一样的,这样能够节省大量的I/O口,而且功耗更低。


以下是MP801开发板对应的数码管原理图,并且是共阳极的数码管:
2.png


Ø  工程架构
根据设计目标将现象翻译成信号表示如下:

第1秒,数码管0显示数字“0”,即seg_sel的值为8’b1111_1110,seg_ment的值为8’b1100_0000;
第2秒,数码管1显示数字“1”,即seg_sel的值为8’b1111_1101,seg_ment的值为8'b1111_1001;
第3秒,数码管2显示数字“2”,即seg_sel的值为8’b1111_1011,seg_ment的值为8'b1010_0100;
第4秒,数码管3显示数字“3”,即seg_sel的值为8’b1111_0111,seg_ment的值为8'b1011_0000;
第5秒,数码管4显示数字“4”,即seg_sel的值为8’b1110_1111,seg_ment的值为8'b1001_1001;
第6秒,数码管5显示数字“5”,即seg_sel的值为8’b1101_1111,seg_ment的值为8'b1001_0010;
第7秒,数码管6显示数字“6”,即seg_sel的值为8’b1011_1111,seg_ment的值为8'b1000_0010;
第8秒,数码管7显示数字“7”,即seg_sel的值为8’b0111_1111,seg_ment的值为8'b1111_1000;

第九秒,回到数码管0显示数字“0”,以此进行循环。

总结发现,数码管每隔1秒进行变化,且8个数码管轮流显示。

因此本工程用到了三个计数器的架构,具体架构如下图所示:
3.JPG


1秒计数器cnt_1s:用于计算1s的时间,加一条件为1,表示一直在计数;数到50,000,000下,表示数到1s就结束。

位选计数器sel_cnt:用于区分选通的数码管,加一条件为end_cnt_1s,表示每间隔1秒的时间后,切换选通下一个数码管;数到8下,表示8个数码管都选通过一轮了。

1.1.5参考代码
  1. module  seg_disp(
  2.                  rst_n       ,
  3.                  clk         ,
  4.                  seg_sel     ,
  5.                  segment      
  6.              );


  7. parameter  TIME_1S        =       50_000_000  ;
  8. parameter  SEG_WID        =       8           ;
  9. parameter  SEG_NUM        =       8           ;
  10. parameter  CNT_WID        =       10          ;
  11. parameter  TIME_20US      =       10'd1000    ;
  12. parameter  NUM_0          =       8'b1100_0000;
  13. parameter  NUM_1          =       8'b1111_1001;
  14. parameter  NUM_2          =       8'b1010_0100;
  15. parameter  NUM_3          =       8'b1011_0000;
  16. parameter  NUM_4          =       8'b1001_1001;
  17. parameter  NUM_5          =       8'b1001_0010;
  18. parameter  NUM_6          =       8'b1000_0010;
  19. parameter  NUM_7          =       8'b1111_1000;
  20. parameter  NUM_8          =       8'b1000_0000;
  21. parameter  NUM_9          =       8'b1001_0000;
  22. parameter  NUM_ERR        =       8'b1111_1111;


  23. input                             clk         ;
  24. input                             rst_n       ;
  25. output [SEG_WID - 1:0]            seg_sel     ;
  26. output [SEG_WID - 1:0]            segment     ;

  27. reg    [SEG_WID - 1:0]            seg_sel     ;
  28. reg    [SEG_WID - 1:0]            segment     ;

  29. reg    [ 31    :    0]            cnt_1s      ;
  30. reg    [SEG_NUM - 1:0]            sel_cnt     ;

  31. reg    [ 4 - 1 :    0]            seg_tmp     ;

  32. wire                              add_cnt_1s  ;
  33. wire                              end_cnt_1s  ;
  34. wire                              add_sel_cnt ;
  35. wire                              end_sel_cnt ;


  36. always @(posedge clk or negedge rst_n) begin
  37.     if (rst_n==0) begin
  38.         cnt_1s <= 0;
  39.     end
  40.     else if(add_cnt_1s) begin
  41.         if(end_cnt_1s)
  42.             cnt_1s <= 0;
  43.         else
  44.             cnt_1s <= cnt_1s+1 ;
  45.    end
  46. end
  47. assign add_cnt_1s = 1;
  48. assign end_cnt_1s = add_cnt_1s  && cnt_1s == TIME_1S-1 ;


  49. always  @(posedge clk or negedge rst_n)begin
  50.     if(rst_n==1'b0)begin
  51.         sel_cnt <= 0;
  52.     end
  53.     else if(add_sel_cnt)begin
  54.         if(end_sel_cnt)
  55.             sel_cnt <= 0;
  56.         else
  57.             sel_cnt <= sel_cnt + 1;
  58.     end
  59. end
  60. assign add_sel_cnt = end_cnt_1s;
  61. assign end_sel_cnt = add_sel_cnt && sel_cnt == SEG_NUM-1;

  62. always  @(posedge clk or negedge rst_n)begin
  63.     if(rst_n==1'b0)begin
  64.         seg_sel <= {SEG_NUM{1'b1}};
  65.     end
  66.     else begin
  67.         seg_sel <= ~(1'b1 << sel_cnt);
  68.     end
  69. end

  70. always  @(*)begin
  71.     if(rst_n==1'b0)
  72.         seg_tmp = {SEG_NUM{1'b1}};
  73.     else
  74.         seg_tmp = sel_cnt ;
  75. end



  76. always@(posedge clk or negedge rst_n)begin
  77.     if(rst_n==1'b0)begin
  78.         segment<=NUM_0;
  79.     end
  80.     else  begin
  81.         case (seg_tmp)
  82.             0 : segment <= NUM_0;
  83.             1 : segment <= NUM_1;
  84.             2 : segment <= NUM_2;
  85.             3 : segment <= NUM_3;
  86.             4 : segment <= NUM_4;
  87.             5 : segment <= NUM_5;
  88.             6 : segment <= NUM_6;
  89.             7 : segment <= NUM_7;
  90.             8 : segment <= NUM_8;
  91.             9 : segment <= NUM_9;
  92.             default : segment <= NUM_ERR;
  93.         endcase
  94.     end
  95. end

  96. endmodule
复制代码


1.2 效果和总结


&#216;  下图是该工程在db603开发板上的现象
4.jpg


&#216;  下图是该工程在mp801开发板上的现象
5.jpg


&#216;  下图是该工程在ms980试验箱上的现象
6.jpg




由于该项目的上板现象是上电数码管从左到右流动显示对应的数值,想观看完整现象的朋友可以看一下现象演示的视频。
感兴趣的朋友也可以访问明德扬论坛(http://www.FPGAbbs.cn/)进行FPGA相关工程设计学习,也可以看一下我们往期的文章:

1.3 公司简介
明德扬是一家专注于FPGA领域的专业性公司,公司主要业务包括开发板、教育培训、项目承接、人才服务等多个方向。点拨开发板——学习FPGA的入门之选。
MP801
开发板——千兆网、ADDA、大容量SDRAM等,学习和项目需求一步到位。网络培训班——不管时间和空间,明德扬随时在你身边,助你快速学习FPGA周末培训班——明天的你会感激现在的努力进取,升职加薪明德扬来助你。就业培训班——七大企业级项目实训,获得丰富的项目经验,高薪就业。专题课程——高手修炼课:提升设计能力;实用调试技巧课:提升定位和解决问题能力;FIFO架构设计课:助你快速成为架构设计师;时序约束、数字信号处理、PCIE、综合项目实践课等你来选。项目承接——承接企业FPGA研发项目。人才服务——提供人才推荐、人才代培、人才派遣等服务。



【设计教程下载】
至简设计系列_7段数码管显示 .pdf (1.54 MB, 下载次数: 9)
FPGA视频课程  培训班 FPGA学习资料
吴老师 18022857217(微信同号) Q1241003385
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号-1

GMT+8, 2021-4-10 23:13 , Processed in 0.527815 second(s), 14 queries , File On.

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

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