FPGA02_七段数码管显示译码器设计与应用

七段数码管显示译码器设计与应用

背景

七段数码管是由 7+1 个 LED 构成的数字显示器件,其中前面七个 LED 各自显示数字的一段,最后的一个LED显示小数点。它有十二个引脚,其中八个引脚用于控制七段数码管显示什么图案,四个引脚分别作为四位七段数码管的使能信号,即分别控制四位七段数码管是否显示该图案。

笔者使用的 Arduino 板的 LED 是 共阳极的,因此低电平才能点亮,即当信号为 0 时亮起,为 1 时熄灭。为了节约管脚,它们都使用了同一组输入信号,因此同一时间四个七段数码管都会显示相同的内容。如下图:

Working principle of 7-Segment display

本次我们要使用七段数码管实现十六进制译码器 (Hex 7-Segment Decoder Display),并且实现数码管显示功能。

真值表与电路设计

七段数码管可以将十六进制数字以下图的形式显示:

因此我们可以设计出如下的真值表:

$X_b$$X_h$$a$$b$$c$$d$$e$$f$$g$
000000000001
000111001111
001020010010
001130000110
010041001100
010150100100
011060100000
011170001111
100080000000
100190000100
1010A0001000
1011B1100000
1100C0110001
1101D1000010
1110E0110000
1111F0111000

如果我们设四位输入信号(16位译码器是 4-16 的) 为 $I_0,I_1,I_2,I_3$ ,那么输出到七个引脚 $a,b,c,d,e,f,g,h$ 的信号可看作是七个关于这四位输入信号的布尔函数。对每个布尔函数我们都可以画出相应的电路图,但是感觉有些复杂,为什么我们不能进行化简呢?正好输入信号就是四位,可以使用 K-map 优化,事情就这样成了,比如 $a,b,e$ 这三个引脚的优化:

7SD_Kmap.png

根据卡诺图我们可以得到:

a=I3I2I1I0+I3I2I1I0+I3I2I1I0+I3I2I1I0b=I3I2I1I0+I2I1I0+I3I1I0+I3I2I0e=I3I0+I3I2I1+I2I1I0\begin{aligned} a &= \overline{I_3} \cdot \overline{I_2} \cdot \overline{I_1} \cdot I_0+ \overline{I_3} \cdot I_2 \cdot \overline{I_1} \cdot \overline{I_0} +I_3 \cdot \overline{I_2} \cdot I_1 \cdot I_0+I_3 \cdot I_2 \cdot \overline{I_1} \cdot I_0\\ b &= \overline{I_3} \cdot I_2 \cdot \overline{I_1} \cdot I_0+I_2 \cdot I_1 \cdot \overline{I_0} +I_3 \cdot I_1 \cdot I_0+I_3 \cdot I_2 \cdot \overline{I_0} \\ e &= \overline{I_3} \cdot I_0+ \overline{I_3} \cdot I_2 \cdot \overline{I_1} + \overline{I_2} \cdot \overline{I_1} \cdot I_0\\ \end{aligned}

同理其它引脚的表达式也如下:

$$ \begin{aligned} c &= \overline{I_3} \cdot \overline{I_2} \cdot I_1 \cdot \overline{I_0} +I_3 \cdot I_2 \cdot \overline{I_0} +I_3 \cdot I_2 \cdot I_1\\ d &= \overline{I_3} \cdot \overline{I_2} \cdot \overline{I_1} \cdot I_0+ \overline{I_3} \cdot I_2 \cdot \overline{I_1} \cdot \overline{I_0} +I_2 \cdot I_1 \cdot I_0+I_3 \cdot \overline{I_2} \cdot I_1 \cdot \overline{I_0} \\ f &= \overline{I_3} \cdot \overline{I_2} \cdot I_0+ \overline{I_3} \cdot \overline{I_2} \cdot I_1+ \overline{I_3} \cdot I_1 \cdot I_0+I_3 \cdot I_2 \cdot \overline{I_1} \cdot I_0\\ g &= \overline{I_3} \cdot \overline{I_2} \cdot \overline{I_1} + \overline{I_3} \cdot I_2 \cdot I_1 \cdot I_0+I_3 \cdot I_2 \cdot \overline{I_1} \cdot \overline{I_0} \\ \end{aligned} $$

根据简化后的表达式,我们可以画出如下的电路图:

7_Segment_Display_Original_Circuit.png

在 Logisim 上模拟运行的结果如下

Seven_Segment_Circuit.gif

仿真激励与上板验证

我们将画好图的模块导出为 verilog 文件 MyMC14495.v ,并且为其编写激励模块:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
module MyMC14495_tb();

    reg EN;
    reg [3:0] I;
    wire p;
    wire a;
    wire b;
    wire c;
    wire d;
    wire e;
    wire f;
    wire g;

    MyMC14495  simu_MC14495(.EN(EN), 
                            .I0(I[0]), 
                            .I1(I[1]), 
                            .I2(I[2]), 
                            .I3(I[3]),
                            .a(a),
                            .b(b),
                            .c(c),
                            .d(d),
                            .e(e),
                            .f(f),
                            .g(g));
    
    integer i;
    initial begin
	    I[3] = 0;
	    I[2] = 0;
	    I[1] = 0;
	    I[0] = 0;
	    EN = 0;
        for(i=0;i<=15;i=i+1)begin
            #50;
            {I[3],I[2],I[1],I[0]}=i;
        end

        #50;
        EN = 1;
    end
endmodule

在 Vivado 上运行仿真激励得到如下结果:

Behaviour_Simulation_Waveform_Diagram.png

使用 Verilog 进行接线,编写引脚约束文件。上板验证,但是有盒我就不放图图了。

使四个七段数码管同时显示四个数字?

可以利用视觉残留效应:当物体在快速运动时, 人眼所看到的影像消失后,人眼仍能继续保留其影像 $\frac{1}{24}$ 秒左右的图像,因此我们可以用时钟作为选择器,以一定的(足够高的)频率输出四位的信号控制四个数码管的使能端,使得每次只亮起一个数码管,这个数码管显示的是其对应的数字(类似于显示器的扫描线)。这样的话,在第二个数字亮起的同时,上一个数字的像还没有从人眼中消失,在视觉上便得到了同时显示四个数字的效果:

Time$E_3E_2E_1E_0$$O$
01110N_0
11101N_1
21011N_2
30111N_3
41110N_0

因为是四个数码管,因此这四段数码管应该在 $\frac{1}{24}$ 秒内完成一次扫描循环,单个数码管亮起熄灭的时间则是 $\frac{1}{24}\cdot\frac{1}{4}=\frac{1}{96}$ 秒。 这是我下周将要实现的内容。下播。

使用 Hugo 构建
主题 StackJimmy 设计