设计背景:
数码管是一种半导体发光器件,其基本单元是发光二极管。数码管在我们的许多设计中都又用到,数码管的显示原理简单和显示效果清晰在我们的工业中的到了广泛的应用。
数码管的应用很广泛,涉及众多领域,我们就拿数显仪表这个领域来讲,数显仪表是数字式显示仪表的简称,显示器常用的有LED、LCD为显示元件。
设计原理:
本次的设计是设计一个数码管的显示模,其设计原理图如下:
数码管显示分为的动态和静态显示,为了让人眼可以看清数码管的显示,我们一般驱动数码管的频率为1K - 10K 之间。
顾名思义,七段数码管就是使用七段点亮的线段来拼成常见的数字和某些字母,这种显示方式我们在数字电路中非常容易见到。再加上右下角显示的小数点,实际上一个显示单元包括了8根信号线。根据电路设计的不同,这些信号线可能高有效也可能低有效。我们通过FPGA控制这些线段的亮灭,达到显示效果。
对于多个数码管的显示模块,将每一个都连接到FPGA的管脚会耗用大量FPGA的管脚资源。因此我们同样引入一种类似矩阵键盘的扫描方式。任何时刻我们只使用8根信号点亮一个数码管,但是8个数码管是随着时钟步调交替点亮的,只要时钟的速度够快,我们观察到数码管就好像几个同时点亮一样。
我们的开发板使用的动态显示来循环扫描显示。其原理图如下所示:
如图所示,我们的开发板使用的是六位共阳极数码管,六个PNP型三极管分别作为六组数码管电源的输入开关,也就是我们常说的位选信号,PNP三极管为低电平导通,所以我们的位选信号低有效。在这里,为了节约FPGA的IO资源,我们把六个位选信号连接到了三八译码器74HC138D。
从我们的板子硬件原理图上我们可以看清,我们的数码管是红阳极,就是是给一个低电平就是点亮数码管的一个段,那么8段全部给8’b0000000那么数码管显示的就是8这个数字了,我们用的是循环显示,是通过sel引脚来选择哪一个数码管亮,也就是说我们的sel的三位为3’b000的时候也就是选择第一个数码亮,3’b001第二个数码管亮依次类推。
设计架构图:
设计代码:
顶层模块
0moduleseg_x(clk,rst_n,sel,seg7);//顶层端口
1 inputclk; //输入
2 inputrst_n;
3 output[2:0]sel; //输出
4 output[7:0]seg7;
5
6 wire[23:0]num;
7
8 num_in num_in( //例化输入模块
9 .clk(clk),
10 .rst_n(rst_n),
11 .num(num)
12 );
13
14 seg seg( //例化数码管模块
15 .clk(clk),
16 .rst_n(rst_n),
17 .sel(sel),
18 .seg7(seg7),
19 .data_in(num)
20 );
21endmodule
设计模块
0moduleseg(clk,rst_n,sel,seg7,data_in);//端口定义
1
2 inputclk;
3 inputrst_n;
4 input[23:0]data_in;//输入6个灯的数据
5
6 outputreg[2:0]sel;
7 outputreg[7:0]seg7;
8
9 parameters0 =3'b000;
10 parameters1 =3'b001;
11 parameters2 =3'b010;
12 parameters3 =3'b011;
13 parameters4 =3'b100;
14 parameters5 =3'b101;
15
16 `defineT1ms 50_000 //定义1k的计数值
17 //`define T1ms 5
18 reg[15:0]count;
19 wireflag;
20 always@(posedgeclk ornegedgerst_n)
21 if(!rst_n)
22 begin
23 count <=15'b0;
24 end
25 else
26 if(count ==`T1ms-1)//计数到1MS
27 begin
28 count <=15'b0;
29 end
30 else
31 begin
32 count <=count +1'b1;
33 end
34
35 assignflag =(count ==`T1ms-1)?1'b1:1'b0;//标志位赋值
36
37 reg[2:0]state;
38 reg[3:0]num;
39 always@(posedgeclk ornegedgerst_n)
40 if(!rst_n)
41 begin
42 sel <=3'b0;
43 state <=3'b0;
44 num <=4'b0;
45 end
46 else
47 begin
48 case(state)
49 s0:begin
50 if(flag)
51 state <=s1;//亮第一个灯,给24位数据的 4位
52 else
53 begin
54 sel <=3'b000;
55 num <=data_in[23:20];
56 end
57 end
58 s1:begin
59 if(flag) ////亮第2个灯,给24位数据 的4位
60 state <=s2;
61 else
62 begin
63 sel <=3'b001;
64 num <=data_in[19:16];
65 end
66 end
67 s2:begin
68 if(flag) //亮第3个灯,给24位数据的 4位
69 state <=s3;
70 else
71 begin
72 sel <=3'b010;
73 num <=data_in[15:12];
74 end
75 end
76 s3:begin
77 if(flag) //亮第4个灯,给24位数据的4位
78 state <=s4;
79 else
80 begin
81 sel <=3'b011;
82 num <=data_in[11:8];
83 end
84 end
85 s4:begin
86 if(flag) //亮第5个灯,给24位数据的4位
87 state <=s5;
88 else
89 begin
90 sel <=3'b100;
91 num <=data_in[7:4];
92 end
93 end
94 s5:begin
95 if(flag) //亮第6个灯,给24位数据的4位
96 state <=s0;
97 else
98 begin
99 sel <=3'b101;
100 num <=data_in[3:0];
101 end
102 end
103 default:state <=s0;
104 endcase
105 end
106
107 always@(*) //数码管的译码模块
108 begin
109 case(num)
110 0:seg7 =8'b1100_0000;
111 1:seg7 =8'b1111_1001;
112 2:seg7 =8'b1010_0100;
113 3:seg7 =8'b1011_0000;
114 4:seg7 =8'b1001_1001;
115 5:seg7 =8'b1001_0010;
116 6:seg7 =8'b1000_0010;
117 7:seg7 =8'b1111_1000;
118 8:seg7 =8'b1000_0000;
119 9:seg7 =8'b1001_0000;
120 10:seg7 =8'b1000_1000;
121 11:seg7 =8'b1000_0011;
122 12:seg7 =8'b1100_0110;
123 13:seg7 =8'b1010_0001;
124 14:seg7 =8'b1000_0110;
125 15:seg7 =8'b1000_1110;
126 default:;
127 endcase
128 end
129endmodule
输入模块
0modulenum_in(clk,rst_n,num);//端口定义
1 inputclk;
2 inputrst_n;
3
4
5 output[23:0]num;
6
7 assignnum =24'h123456;//给输入一个值,便于下次直接调用
8
9
10
11endmodule
测试模块
0`timescale1ns/1ps//时间精度
1
2moduleseg_tb;
3 regclk; //端口定义
4 regrst_n;
5
6
7 wire[2:0]sel;
8 wire[7:0]seg7;
9
10 initialbegin
11 clk =1'b1;
12 rst_n =1'b0;
13
14 #100.1rst_n =1'b1;
15
16 #200000
17 $stop;
18
19 end
20 always#10clk =~clk;//模拟时钟
21
22 seg_x seg_x_dut( //例化顶层模块
23 .clk(clk),
24 .rst_n(rst_n),
25 .sel(sel),
26 .seg7(seg7)
27 );
28endmodule
仿真图:
在仿真中我们可以看到我们的设计是正确的,第一个灯亮的是f9,也就是也就是对应数码管显示的是1,a4就是2,和我们的输入是正确的。
-
FPGA
+关注
关注
1629文章
21731浏览量
603064 -
数码管
+关注
关注
32文章
1882浏览量
91073
发布评论请先 登录
相关推荐
评论