当前位置:   article > 正文

FPGA开发——数码管的使用

FPGA开发——数码管的使用

一、概述

在我们的日常开发中,数字显示的领域中用得最多的就是数码管,这篇文章也是围绕数码管的静态显示和动态显示进行一个讲解。

1、理论

(1)数码管原理图

在对数码管进行相关控制时,其实就是对于8段发光二极管和一个位选信号进行控制,也就是我们熟悉的段选和位选。段选就包括a,b,c,d,e,f,g,h这八个二极管,位选就是选择某个二极管工作的一个简单引脚。

2、共阴极和共阳极的判断

市场上我们常见的数码管有共阴极啊和共阳极两种信号,其外观上没有什么区别,都是通过原理图进行判断和区分,两种数码挂对应的驱动方式也不一样。共阴极是高电平驱动,共阳极是低电平驱动。所谓的共阴极和共阳极实际上就是看公共引脚接在正极还是负极上。

 

3、本次使用的数码管原理图

其实在原理图中并没有明确说明是共阴极还是共阳极,我们需要通过SEL位选信号进行判断。在最下面的三极管我们可以看到只有当SELx_T为低电平时三极管才会接通,所以这里通过判断是共阳极,通过低电平触发。

 二、工程实现

1、单个数码管静态显示

(1)、设计文件

新建seg.v文件,如下:

这里不需要使用任何时序功能,只是简单显示一个数字,直接就用连续赋值进行实现。这里代码过于简单,就不去进行仿真和下板验证了。

  1. module top(
  2. output seg_sel,
  3. output [7:0] seg_dual
  4. );
  5. assign seg_sel=1'b0;//选择第一个数码管
  6. assign seg_dual=8'b11_000_000;//数码管显示0

2、单个数码管实现动态显示

(1)、设计文件

  1. //分频器
  2. module seg0(
  3. input clk,
  4. input rst_n,
  5. input seg_sel,//位选
  6. output reg [7:0] seg_dual0//段选
  7. );
  8. localparam ZERO = 8'b11100_0000, //共阳极段码
  9. ONE = 8'b11111_1001,
  10. TWO = 8'b11010_0100,
  11. THREE = 8'b11011_0000,
  12. FOUR = 8'b11001_1001,
  13. FIVE = 8'b11001_0010,
  14. SIX = 8'b11000_0010,
  15. SEVEN = 8'b11111_1000,
  16. EIGHT = 8'b11000_0000,
  17. NINE = 8'b11001_0000,
  18. A = 8'b11000_1000,
  19. b = 8'b11000_0011,
  20. c = 8'b11100_0110,
  21. d = 8'b11010_0001,
  22. E = 8'b11000_0110,
  23. f = 8'b11000_1110;
  24. reg [26:0] cnt;
  25. wire add_cnt;
  26. wire end_cnt;
  27. reg [4:0] flag;
  28. wire add_flag;
  29. wire end_flag;
  30. always @(posedge clk or negedge rst_n)begin
  31. if(!rst_n)
  32. cnt<=0;
  33. else if(add_cnt)begin
  34. if(end_cnt)
  35. cnt<=0;
  36. else
  37. cnt<=cnt+1'b1;
  38. end
  39. end
  40. assign add_cnt=1'b1;
  41. assign end_cnt=add_cnt && (cnt==50_000_000-1);
  42. always @(posedge clk or negedge rst_n)begin
  43. if(!rst_n)
  44. flag<=0;
  45. else if(add_flag)begin
  46. if(end_flag)
  47. flag<=0;
  48. else
  49. flag<=flag+1'b1;
  50. end
  51. end
  52. assign add_flag=end_cnt;
  53. assign end_flag=add_flag && (flag==16-1);
  54. always @(posedge clk or negedge rst_n)begin
  55. if(!rst_n)
  56. seg_dual0<=8'b1111_1111;
  57. else begin
  58. case (flag)
  59. 4'd0:seg_dual0<=ZERO ;
  60. 4'd1:seg_dual0<=ONE ;
  61. 4'd2:seg_dual0<=TWO ;
  62. 4'd3:seg_dual0<=THREE;
  63. 4'd4:seg_dual0<=FOUR ;
  64. 4'd5:seg_dual0<=FIVE ;
  65. 4'd6:seg_dual0<=SIX ;
  66. 4'd7:seg_dual0<=SEVEN;
  67. 4'd8:seg_dual0<=EIGHT;
  68. 4'd9:seg_dual0<=NINE ;
  69. 4'd10:seg_dual0<=A ;
  70. 4'd11:seg_dual0<=b ;
  71. 4'd12:seg_dual0<=c;
  72. 4'd13:seg_dual0<=d;
  73. 4'd14:seg_dual0<=E ;
  74. 4'd15:seg_dual0<=f ;
  75. default: ;
  76. endcase
  77. end
  78. end
  79. endmodule

(2)、测试文件

  1. //定义时间尺度
  2. `timescale 1ns/1ns
  3. module seg_tb ;
  4. //输入信号定义
  5. reg clk;
  6. reg rst_n;
  7. wire [7:0] seg_dual0;
  8. wire seg_sel;
  9. defparam seg0_inst.TIME_1s=500;
  10. //模块例化
  11. seg0 seg0_inst(
  12. /*input */.clk (clk ),
  13. /*input */.rst_n (rst_n ),
  14. /*output*/.seg_sel (seg_sel ),
  15. /*output*/.seg_dual0 (seg_dual0)
  16. );
  17. //激励信号产生
  18. parameter CLK_CLY = 20;
  19. //时钟
  20. initial clk=1;
  21. always #(CLK_CLY/2)clk=~clk;
  22. //复位
  23. initial begin
  24. rst_n= 1'b0;
  25. #(CLK_CLY*3);
  26. #5;//复位结束避开时钟上升沿
  27. rst_n= 1'b1;
  28. end
  29. endmodule

(3)、波形图仿真

在波形图中我们可以看到段选从8'b11_000_000——8'b11_000_1110,也就是从0——F动态显示。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/909195
推荐阅读
相关标签
  

闽ICP备14008679号