数码管驱动电路设计
数码管----SEG一、 简单介绍
顾名思义,七段数码管就是使用七段点亮的线段来拼接成常见的数字和某些字母,这种显示方式我们在数字电路中非常容易见到。再加上右下角显示的小数点,实际上一个显示单元包括了8根信号线,根据电路设计的不同,这些信号线可能高电平有效,也可能低电平有效。我们通过fpga控制这些线段的亮灭,就可以达到相应的显示效果。
对于多个数码管的显示模块,将每一个都连接到fpga的引脚会耗用大量的fpga的引脚资源。因此我们同样引入一种类似矩阵键盘的扫描方式。任何时刻我们只使用8根信号点亮一个数码管,但是8个数码管是随着时钟步调交替点亮的,只要时钟的速度够快,我们观察到数码管就好像几个同时点亮一样,开发板原理图如下:
如图所示,我们的开发板使用是六位共阳极数码管个 PNP PNP型三极管 分别作为六组数码管电源的输入开关, 也就是我们常说位选信号分别作为六组数码管电源的输入开关, 也就是我们常说位选信号PNP PNP三极管 为低电平导通,所以我们的位选信号有效。在这里了节约 为低电平导通,所以我们的位选信号有效。在这里了节约 为低电平导通,所以我们的位选信号有效。在这里了节约 为低电平导通,所以我们的位选信号有效。在这里了节约 FPGA FPGAFPGA的 IO 资源, 我们把六个位选信号连接到了三八译码器 74HC138D74HC138D 74HC138D 74HC138D ,该三八译码器的真值表如 该三八译码器的真值表如下:
由此,我们可以得出结论当 {SEL2, SEL1, SEL0}=3’b000时,Y0变为低电平,而由于 Y0 连接到了第一个数码管,所以第一个数码管点亮。当{SEL2, SEL1, SEL0}=3’b001时,对应第二个数码管点亮,以此类推。SEG_0 到SEG_7分别对应二极管 a-g以及“小数点”, 以及“小数点”,以及“小数点”,即我们所说的段选信号。由于是共阳极数码管,所以二极管只要给低电平就可点亮,根据点亮的二极管不同,就可以显示出不同的字符。假如我们要点亮第一个数码管,并且显示出字符“A”,那么我们只需要选中第一个数码管{SEL2, SEL1, SEL0}=3’b000,而且SEG=8’1000_1000。
二、 设计需求
点亮6个数码管,当开关按下时,6个数码管全灭,否则,在数码管上显示字符“123456”。
三、 顶层架构设计
四、 建模与验证
/*Author : 至芯科技
Data :2017/2/21
Mode : freq
*/
00 module freq(clk, rst_n, clk_slow);
01
02 input clk;
03 input rst_n;
04 output reg clk_slow; //1KHZ
05
06 reg counter;
07
08 always @ (posedge clk or negedge rst_n)
09 begin
10 if(!rst_n)
11 begin
12 clk_slow <= 0;
13 counter <= 0;
14 end
15 else if(counter < 24_999)
16 counter <= counter + 1;
17 else
18 begin
19 counter <= 0;
20 clk_slow <= ~clk_slow;
21 end
22 end
23
24 endmodule
25
/*Author : 至芯科技
Data :2017/2/21
Mode : seg_control
*/
00 module seg_control(clk, rst_n, data_in, sel, seg);
01
02 input clk, rst_n;
03 input data_in;
04 output reg sel;
05 output reg seg;
06
07 reg data_r;
08 reg state;
09
10 always @ (posedge clk or negedge rst_n)
11 begin
12 if(!rst_n)
13 begin
14 data_r <= 0;
15 state <= 0;
16 sel <= 0;
17 end
18 else
19 case(state)
20 0 : begin
21 sel = 3'd0;
22 data_r <= data_in;
23 state <= 1;
24 end
25 1 : begin
26 sel = 3'd1;
27 data_r <= data_in;
28 state <= 2;
29 end
30
31 2 : begin
32 sel = 3'd2;
33 data_r <= data_in;
34 state <= 3;
35 end
36
37 3 : begin
38 sel = 3'd3;
39 data_r <= data_in;
40 state <= 4;
41 end
42
43 4 : begin
44 sel = 3'd4;
45 data_r <= data_in;
46 state <= 5;
47 end
48
49 5 : begin
50 sel = 3'd5;
51 data_r <= data_in;
52 state <= 0;
53 end
54
55 default : state <= 0;
56 endcase
57 end
58
59 always @ (*)
60 begin
61 if(!rst_n)
62 seg = 8'hff;
63 else
64 case(data_r)
65 0 : seg = 8'b1100_0000;
66 1 : seg = 8'b1111_1001; //显示’1‘
67 2 : seg = 8'b1010_0100; //显示’2‘
68 3 : seg = 8'b1011_0000; //显示’3‘
69 4 : seg = 8'b1001_1001; //显示’4‘
70 5 : seg = 8'b1001_0010; //显示’5‘
71 6 : seg = 8'b1000_0010; //显示’6‘
72 7 : seg = 8'b1111_1000; //显示’7‘
73 8 : seg = 8'b1000_0000; //显示’8‘
74 9 : seg = 8'b1001_0000; //显示’9‘
75 10 : seg = 8'b1000_1000; //显示’A‘
76 11 : seg = 8'b1000_0011; //显示’B‘
77 12 : seg = 8'b1100_0110; //显示’C‘
78 13 : seg = 8'b1010_0001; //显示’D‘
79 14 : seg = 8'b1000_0110; //显示’E‘
80 15 : seg = 8'b1000_1110; //显示’F‘
81 default : seg = 8'b1100_0000;
82 endcase
83 end
84
85 endmodule
86
/*Author : 至芯科技
Data :2017/2/21
Mode : seg
*/
00 module seg(clk, rst_n,/* data_in,*/ sel, seg);
01
02 input clk,rst_n;
03 // input data_in;
04 output sel;
05 output seg;
06
07 wire clk_slow;
08
09 parameter data_in = 24'h123456;
10
11 freq freq(
12 .clk(clk),
13 .rst_n(rst_n),
14 .clk_slow(clk_slow)
15 );
16
17 seg_control seg_con(
18 .clk(clk_slow),
19 .rst_n(rst_n),
20 .data_in(data_in),
21 .sel(sel),
22 .seg(seg)
23 );
24
25 endmodule
26
RTL级视图如下:
下板验证:
嗯嗯,学习了,谢谢楼主分享! 666.很详细,看的很懂 楼主,sel赋值是非阻塞赋值吧 逆战 发表于 2017-2-26 09:04
楼主,sel赋值是非阻塞赋值吧
是的,在上传的时候,遗漏了,谢谢发现问题! 谢谢楼主分享,很清楚的数码管驱动设计
页:
[1]