基于VHDL的数字秒表设计

当今社会正朝着电子市场发展,越来越多的电子产品应用于各个领域。数字秒表是日常生活中比较常见的电子产品,常用于体育比赛和时间计时,计时的精准性和稳定性是衡量数字秒表最重要的两个指标。现在市场上的数字秒表基本上都能满足计时准确的要求,但很少能满足计时稳定性的要求。本文设计了一种用于精确计时且计时稳定性高的数字秒表,该设计是在Quartus Ⅱ环境下,基于 VHDL语言来编写的,具有开关、计时和显示功能,其计时精度可达0.01s,计时范围较大,计时稳定性好。该设计具有很强的实用性,有着非常广泛的应用。

实验选题及目标

实验选题

在科技高度发展的今天,集成电路和计算机应用得到了高速发展。尤其是计算机应用的发展,它在人们日常生活中已逐渐崭露头角,大多数电子产品多是有计算机电路组成,如:手机、mp3等。而且将来的不久他们的身影将会频繁的出现在我们身边,各种家用电器多会实现微电脑技术,电脑各部分在工作时多是一时间为基准的。

本文就是基于计算机电路的时钟脉冲信号、状态控制等原理设计出的数字秒表。秒表在很多领域充当一个重要角色,在各种比赛中对秒表的精确度要求很高,尤其是一些科学实验,他们对时间精确度达到了几纳秒级别。数字秒表具有操作方便、使用简单、计数精准等使用优点,在日常生活中的到了广泛认可和使用。

实验目标

设计一块数字秒表,能够精确反映计时时间,并完成复位、计时功能。秒表的计时范围为0秒~ 59分59.99秒,精度为0.01秒,并可显示计时时间的分、秒、毫秒等度量。

(1)具有秒表系统功能要求显示功能, 用8个数码管分别显示时、分、秒、毫秒,计时范围为00: 00: 00~ 59: 59:99。 

(2)数字秒表计时精度是0.01s。

(3)具有启/ 停开关, 复位开关,复位开关在任何情况下都能使用,使计实清零。

实验内容

根据系统设计要求, 系统的底层设计主要由控制模块、分频模块、计时模块、显示模块四部分组成。系统顶层设计图如图所示:

图中左边为三个输入信号CLK、CLR、SP分别为时钟信号、复位开关和启/ 停开关。主要模块有:分频模块(CB10),时间计数器(COUNT),复位控制(CONTROL),数据选择模块(MULX),译码器(BCD7)。右边为五个输出信号LED、OUTBCD、SEG、CO、EN分别为七段式LED码值、输出时间值、数码管位选、分频信号和使能信号。

由模10计数器模块与模6计数器模块进行计数;实验室仪器可产生标准的50mHz的时钟信号,通过分频器模块产生所需的1kHz的时钟信号;复位模块可进行计数器复位操作;译码器是为了将四位二进制信号转换为LED所需的七位二进制编码;状态变换模块是为了用户按键后信号的变换及保持。

RTL图

实验开发环境与器材

Quartus Ⅱ 9.1和FPGA器件EP2C35F484C8

实验代码

CB10.vhd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CB10 IS
PORT(CLK : IN STD_LOGIC;
CO : OUT STD_LOGIC);
END CB10;
ARCHITECTURE one OF CB10 IS
SIGNAL CNTER : STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
PROCESS(CLK)
BEGIN
IF(RISING_EDGE(CLK)) THEN
IF CNTER = "1100001101001111" THEN --49999
CNTER<="0000000000000000";
CO<='1';
ELSE
CNTER<=CNTER+1;
CO<='0';
END IF;
END IF;
END PROCESS;
END one;

CONTROL.vhd

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
43
44
45
46
47
48
49
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CONTROL IS
PORT(CLR,CLK,SP : IN STD_LOGIC;
EN : OUT STD_LOGIC);
END;
ARCHITECTURE one OF CONTROL IS
TYPE STATES IS (S0,S1,S2,S3);
SIGNAL CURRENT_STATE,NEXT_STATE:STATES;
BEGIN
COM:PROCESS(SP,CURRENT_STATE)
BEGIN
CASE CURRENT_STATE IS
WHEN S0=> EN<='0';
IF SP='1' THEN
NEXT_STATE<=S1;
ELSE
NEXT_STATE<=S0;
END IF;
WHEN S1=> EN<='1';
IF SP='1' THEN
NEXT_STATE<=S1;
ELSE
NEXT_STATE<=S2;
END IF;
WHEN S2=> EN<='1';
IF SP='1' THEN
NEXT_STATE<=S3;
ELSE
NEXT_STATE<=S2;
END IF;
WHEN S3=> EN<='0';
IF SP='1' THEN
NEXT_STATE<=S3;
ELSE
NEXT_STATE<=S0;
END IF;
END CASE;
END PROCESS;
REG:PROCESS(CLK)
BEGIN
IF CLR='1' THEN
CURRENT_STATE<=S0;
ELSIF CLK'EVENT AND CLK='1' THEN
CURRENT_STATE<=NEXT_STATE;
END IF;
END PROCESS;
END;

CDU10.vhd

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
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CDU10 IS
PORT(CLK,CLR,EN : IN STD_LOGIC;
CN : OUT STD_LOGIC;
COUNT10 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END CDU10;
ARCHITECTURE one OF CDU10 IS
SIGNAL SCOUNT10 : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
COUNT10<=SCOUNT10;
PROCESS(CLK,CLR,EN)
BEGIN
IF CLR='1' THEN
SCOUNT10<="0000";
CN<='0';
ELSIF RISING_EDGE(CLK) THEN
IF EN='1' THEN
IF SCOUNT10="1001" THEN
CN<='1';
SCOUNT10<="0000";
ELSE
CN<='0';
SCOUNT10<=SCOUNT10+1;
END IF;
END IF;
END IF;
END PROCESS;
END;

CDU6.vhd

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
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CDU6 IS
PORT(CLK : IN STD_LOGIC;
CLR : IN STD_LOGIC;
EN : IN STD_LOGIC;
CN : OUT STD_LOGIC;
COUNT6 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END CDU6;
ARCHITECTURE one OF CDU6 IS
SIGNAL SCOUNT6 : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
COUNT6<=SCOUNT6;
PROCESS(CLK,CLR,EN)
BEGIN
IF CLR='1' THEN
SCOUNT6<="0000";
CN<='0';
ELSIF RISING_EDGE(CLK) THEN
IF EN='1' THEN
IF SCOUNT6="0101" THEN
CN<='1';
SCOUNT6<="0000";
ELSE
CN<='0';
SCOUNT6<=SCOUNT6+1;
END IF;
END IF;
END IF;
END PROCESS;
END;

COUNT.vhd

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
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY COUNT IS
PORT(CLK,CLR,EN : IN STD_LOGIC;
MS_1MS : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_10MS : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_100MS : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S_1S : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S_10S : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
M_1MIN : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
M_10MIN : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
HOUR : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END;
ARCHITECTURE one OF COUNT IS
COMPONENT CDU10
PORT(CLK,CLR,EN : IN STD_LOGIC;
CN : OUT STD_LOGIC;
COUNT10 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT CDU10;

COMPONENT CDU6
PORT(CLK,CLR,EN : IN STD_LOGIC;
CN : OUT STD_LOGIC;
COUNT6 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT CDU6;
SIGNAL A,B,C,D,E,F,G,H : STD_LOGIC;
BEGIN
U1:CDU10 PORT MAP(CLK=>CLK,CLR=>CLR,EN=>EN,CN=>A,COUNT10=>MS_1MS);
U2:CDU10 PORT MAP(CLK=>A,CLR=>CLR,EN=>EN,CN=>B,COUNT10=>MS_10MS);
U3:CDU10 PORT MAP(CLK=>B,CLR=>CLR,EN=>EN,CN=>C,COUNT10=>MS_100MS);
U4:CDU10 PORT MAP(CLK=>C,CLR=>CLR,EN=>EN,CN=>D,COUNT10=>S_1S);
U5:CDU6 PORT MAP(CLK=>D,CLR=>CLR,EN=>EN,CN=>E,COUNT6=>S_10S);
U6:CDU10 PORT MAP(CLK=>E,CLR=>CLR,EN=>EN,CN=>F,COUNT10=>M_1MIN);
U7:CDU6 PORT MAP(CLK=>F,CLR=>CLR,EN=>EN,CN=>G,COUNT6=>M_10MIN);
U8:CDU10 PORT MAP(CLK=>G,CLR=>CLR,EN=>EN,CN=>H,COUNT10=>HOUR);
END;

MUXL.vhd

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
43
44
45
46
47
48
49
50
51
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY MULX IS
PORT(CLK,CLR,EN : IN STD_LOGIC;
MS_1MS : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_10MS : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_100MS : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S_1S : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S_10S : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
M_1MIN : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
M_10MIN : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
HOUR : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
OUTBCD : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
SEG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END;
ARCHITECTURE one OF MULX IS
SIGNAL COUNT:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(CLK)
BEGIN
IF CLR = '1' THEN
COUNT<="1111";
ELSIF RISING_EDGE(CLK) THEN
IF EN='1' THEN
IF COUNT="0111" THEN
COUNT<="0000";
ELSE
COUNT<=COUNT+'1';
END IF;
END IF;
END IF;
END PROCESS;

PROCESS(CLK)
BEGIN
IF CLK'EVENT AND CLK='1' THEN
CASE COUNT IS
WHEN "0000" => OUTBCD<=MS_1MS; SEG<="11111110";
WHEN "0001" => OUTBCD<=MS_10MS; SEG<="11111101";
WHEN "0010" => OUTBCD<=MS_100MS; SEG<="11111011";
WHEN "0011" => OUTBCD<=S_1S; SEG<="11110111";
WHEN "0100" => OUTBCD<=S_10S; SEG<="11101111";
WHEN "0101" => OUTBCD<=M_1MIN; SEG<="11011111";
WHEN "0110" => OUTBCD<=M_10MIN; SEG<="10111111";
WHEN "0111" => OUTBCD<=HOUR; SEG<="01111111";
WHEN OTHERS => OUTBCD<="0000"; SEG<="00000000";
END CASE;
END IF;
END PROCESS;
END;

BCD7.vhd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY BCD7 IS
PORT(BCD: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
LED: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END;
ARCHITECTURE one OF BCD7 IS
BEGIN
LED <= "1111110" WHEN BCD ="0000" ELSE
"0110000" WHEN BCD ="0001" ELSE
"1101101" WHEN BCD ="0010" ELSE
"1111001" WHEN BCD ="0011" ELSE
"0110011" WHEN BCD ="0100" ELSE
"1011011" WHEN BCD ="0101" ELSE
"1011111" WHEN BCD ="0110" ELSE
"1110000" WHEN BCD ="0111" ELSE
"1111111" WHEN BCD ="1000" ELSE
"1111011" WHEN BCD ="1001" ELSE
"0000000";
END;

Stopwatch.vhd

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY Stopwatch IS
PORT(SP,CLR,CLK :IN STD_LOGIC;
CO,EN : OUT STD_LOGIC;
LED : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
OUTBCD : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
SEG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END;
ARCHITECTURE ONE OF Stopwatch IS
COMPONENT CONTROL
PORT(CLR,CLK,SP : IN STD_LOGIC;
EN : OUT STD_LOGIC);
END COMPONENT;

COMPONENT CB10
PORT(CLK : IN STD_LOGIC;
CO : OUT STD_LOGIC);
END COMPONENT;

COMPONENT COUNT
PORT(CLK,CLR,EN : IN STD_LOGIC;
MS_1MS : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_10MS : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_100MS : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S_1S : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
S_10S : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
M_1MIN : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
M_10MIN : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
HOUR : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT;

COMPONENT BCD7
PORT(BCD: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
LED: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END COMPONENT;

COMPONENT MULX
PORT(CLK,CLR,EN : IN STD_LOGIC;
MS_1MS : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_10MS : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
MS_100MS : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S_1S : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S_10S : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
M_1MIN : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
M_10MIN : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
HOUR : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
OUTBCD : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
SEG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT;

SIGNAL C,E : STD_LOGIC;
SIGNAL MS1,MS10,MS100 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL S1,S10 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL MIN1,MIN10 : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL HR : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL BCD_S : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
U0 : CONTROL PORT MAP(CLR=>CLR,CLK=>CLK,SP=>SP,EN=>E);
U1 : CB10 PORT MAP(CLK=>CLK,CO=>C);
U2 : COUNT PORT MAP(CLK=>C,CLR=>CLR,EN=>E,MS_1MS=>MS1,MS_10MS=>MS10,MS_100MS=>MS100,S_1S=>S1,S_10S=>S10,M_1MIN=>MIN1,M_10MIN=>MIN10,HOUR=>HR);
U3 : MULX PORT MAP(CLK=>CLK,CLR=>CLR,EN=>E,MS_1MS=>MS1,MS_10MS=>MS10,MS_100MS=>MS100,S_1S=>S1,S_10S=>S10,M_1MIN=>MIN1,M_10MIN=>MIN10,HOUR=>HR,OUTBCD=>BCD_S,SEG=>SEG);
U4 : BCD7 PORT MAP(BCD=>BCD_S,LED=>LED);
CO<=C;
EN<=E;
OUTBCD<=BCD_S;
END;

实验流程与步骤

根据系统设计要求, 系统的构成主要由时基分频模块、控制模块、计时模块、显示模块四部分组成,采用自顶向下的方式设计这些模块,系统构成框图如图所示。

(1) 时基分频模块
该分频模块就是把系统工作频率分频后当做定时器的工作频率,例如系统时钟为50MHz,50000分频后定时器的工作时钟为1kHz。

(2) 控制模块
该功能模块是通过对模块的VHDL 程序编译来生成模块的功能元器件,其中
VHDL程序采用状态机描述的方式,状态都采用符号化状态。模块的元器件有三个输入端和一个输出端,其中输入端信号为时钟信号CLK、控制信号SP和复位信号CLR。输入信号SP用于控制计数模块的计时状态,在VHDL程序中设置计时模块有四种状态,分别为s0、s1、s2 和 s3,其中 状态s0是保持态,s1是启动态,s2是计数态,s3是停止态。 输出端为使能信号EN,它是高电平有效。整个程序可分为两个进程来分别描述状态转化机和寄存器操作。在VHDL程序中设置输入信号SP变化时计时模块所对应的状态。通过该设置使得系统可通过控制输入信号SP的值来决定计时模块所处的状态。

(3)计时模块
计时模块共需要2个六进制计数器和6个十进制计数器。其中六进制计数器和十进制计数器的描述方法几乎完全一样。考虑到级联的需要,两个计时器除了时钟输入CLK和异步清零CLR之外,另外设计了计数使能输入端EN,该使能端用于控制计时模块是否工作。

(4)显示模块
数据选择的作用是为了选择计时模块每个位置的数字,并将其对应的数字输出,并设置一个位置标志位来显示输出数字为计时数据的哪一位。显示模块用于显示数据选择器输出端BCD的数据,该显示模块采用的是七段译码器的编译码规则,将ASCII 数据转化为对应的七段译码器数据。计时显示电路的实现方案采用扫描显示,即每次只驱动一位数码管,各位数据轮流驱动对应的数码管进行显示。

系统构成框图

实验结果与分析

数字秒表系统各个模块及整体仿真图如下:

(1)时基分频模块仿真

时基分频模块仿真图

CLK是时钟脉冲输入端,CO为分频后信号输出端。由FPGA器件内部50mHZ的时钟脉冲产生秒表需要的1kHZ时钟频率,需要对50mHZ进行50000分频。

(2)控制模块仿真

控制模块采用高效的状态机控制,模块有四种状态,分别为s0、s1、s2 和 s3,其中 状态s0是保持态,s1是启动态,s2是计数态,s3是停止态。异步清零,秒表在任何时候都能执行清零操作,SP来控制秒表的开始或关闭。

控制模块仿真图

(3)计时模块仿真

①十进制计数器仿真

十进制计数器仿真图

图中可以看出十进制计数器的计数功能正常,从0计到9后回0,清零时立即从0开始计时。

②六进制计数器仿真

六进制计数器仿真图

图中可以看出六进制计数器的计数功能正常,从0计到5后回0,清零时立即从0开始计时。

③计时器仿真

计时器仿真图

计时器功能正常,能够准确计时ms、10ms、100ms、1s、10s、1min、10min、hour位。

(4)显示模块仿真

①数据选择器仿真

数据选择模块选择计时模块每个位置的数字,并将其对应的数字输出,并设置一个位置标志位来显示输出数字为计时数据的哪一位。

数据选择器仿真图

②BCD七段译码器仿真

BCD七段译码器仿真图

(5)秒表系统仿真

秒表系统仿真图

秒表系统仿真正常,从ms位到hour位依次刷新扫描,百进制和六十进制正常,异步清零复位正常,系统整体运行良好。由仿真结果可以看出系统具有计时和显示功能,且满足计时精度为10ms,计时范围为0 ~ 59 分 59.99 秒的设计要求,同时计时稳定性高。

实验体会

VHDL作为一种标准硬件描述语言,它除了含有许多具有硬件特征的语句外,其语言形式和描述风格与句法类似一般的计算机高级语言。VHDL有着与其它语言截然不同的地方,那就是它的互动性很强。因为语言的复杂,老师想要教会我们去用这门语言,光是看书或者PPT是不够的,那样在脑海中的印象并不深刻,所以老师让我们尽量带自己的电脑去上课,在课堂上可以跟着老师一起做。

通过这次课程设计,我了解到了一些自身的不足:对于模块功能想象力不足,模块设计也总是错误百出,粗心大意是永远会出现的。一开始,感觉数字秒表的功能模块应该很清晰,模块之间的联系很密切,同时,觉得自己对于这种简易电子设备的内部结构应该很熟悉。可是,到了真正操作的时候才发现自己想得太简单了。虽然数字秒表就是些简单的计数器的综合,但是每个计数器的设计也是需要懂很多知识的。而且秒表有复位功能,要考虑到复位时同步清零,清零后还要保持在零的状态,清零是用户进行的操纵,需要有外部输入,又要想暂停、启动的控制,这样就需要状态机的模块进行使能端、清零端的状态转换。这些虽然只是细枝末节,但是真正的编程的成功因素很大一部分都是取决于这些细节。

附录(VERILOG)

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
CB10.v
module CB10(clk,co);
input clk;
output co;
reg [3:0] cnter;
reg co;
always@(posedge clk)
begin
if (cnter==4'b1001)
begin
cnter = 0;
co = 1;
end
else
begin
cnter = cnter + 1;
co = 0;
end
end
endmodule

CONTROL.v
module CONTROL(clk,rst,sp,en);
input clk,rst,sp;
output en;
reg en;
parameter s0=0,s1=1,s2=2,s3=3;
reg [3:0] c_st,n_st;
always@(posedge clk or posedge rst)
begin
if(rst)
c_st = s0;
else
c_st = n_st;
end
always@(c_st,sp)
begin
case(c_st)
s0:begin en = 0;
if(sp==1)
n_st = s1;
else
n_st = s0; end
s1:begin en = 1;
if(sp==1)
n_st = s1;
else
n_st = s2; end
s2:begin en = 1;
if(sp==1)
n_st = s3;
else
n_st = s2; end
s0:begin en = 0;
if(sp==1)
n_st = s3;
else
n_st = s0; end
endcase
end
endmodule

CDU10.v
module CDU10(clk,rst,en,cn,count10);
input clk,rst,en;
output cn;
output [3:0] count10;
reg [3:0] count;
reg cn;
assign count10 = count;
always@(posedge clk,posedge rst)
begin
if(rst) begin
count = 0;
cn = 0; end
else if(en) begin
if(count==4'b1001) begin
cn = 1;
count = 0; end
else begin
cn = 0;
count = count+1; end
end
end
endmodule

CDU6.v
module CDU6(clk,rst,en,cn,count6);
input clk,rst,en;
output cn;
output [3:0] count6;
reg [3:0] count;
reg cn;
assign count6 = count;
always@(posedge clk,posedge rst)
begin
if(rst) begin
count = 0;
cn = 0; end
else if(en) begin
if(count==4'b0101) begin
cn = 1;
count = 0; end
else begin
cn = 0;
count = count+1; end
end
end
endmodule

TIMER.v
module TIMER(clk,rst,en,ms1,ms10,ms100,s1,s10,m1,m10,hour);
input clk,rst,en;
output [3:0] ms1,ms10,ms100,s1,s10,m1,m10,hour;
wire a,b,c,d,e,f,g,h;
CDU10 u1(clk,rst,en,a,ms1);
CDU10 u2(a,rst,en,b,ms10);
CDU10 u3(b,rst,en,c,ms100);
CDU10 u4(c,rst,en,d,s1);
CDU6 u5(d,rst,en,e,s10);
CDU10 u6(e,rst,en,f,m1);
CDU6 u7(f,rst,en,g,m10);
CDU10 u8(g,rst,en,h,hour);
endmodule

MUXL.v
module MUXL(clk,rst,en,ms1,ms10,ms100,s1,s10,m1,m10,hour,bcd,seg);
input clk,rst,en;
input [3:0] ms1,ms10,ms100,s1,s10,m1,m10,hour;
output [3:0] bcd;
output [7:0] seg;
reg [3:0] count,bcd;
reg [7:0] seg;
always@(posedge clk,posedge rst)
begin
if(rst)
count = 4'b1111;
else
if(en) begin
if (count==4'b0111)
count = 0;
else
count = count + 1; end
end
always@(posedge clk)
begin
case(count)
4'b0000:begin bcd = ms1;seg = 8'b11111110; end
4'b0001:begin bcd = ms10;seg = 8'b11111101; end
4'b0010:begin bcd = ms100;seg = 8'b11111011; end
4'b0011:begin bcd = s1;seg = 8'b11110111; end
4'b0100:begin bcd = s10;seg = 8'b11101111; end
4'b0101:begin bcd = m1;seg = 8'b11011111; end
4'b0110:begin bcd = m10;seg = 8'b10111111; end
4'b0111:begin bcd = hour;seg = 8'b01111111; end
default:begin bcd = 4'b0000;seg = 8'b0000000; end
endcase
end
endmodule

BCD7.v
module BCD7(bcd,led);
input [3:0] bcd;
output [6:0] led;
reg [6:0] led;
always@(*) begin
case(bcd)
4'b0000:led = 7'b1111110;
4'b0001:led = 7'b0110000;
4'b0010:led = 7'b1101101;
4'b0011:led = 7'b1111001;
4'b0100:led = 7'b0110011;
4'b0101:led = 7'b1011011;
4'b0110:led = 7'b1011111;
4'b0111:led = 7'b1110000;
4'b1000:led = 7'b1111111;
4'b1001:led = 7'b1111011;
default:led = 7'b0000000;
endcase
end
endmodule

Stopwatch.v
module SPWATCH(clk,rst,sp,co,led,seg);
input sp,rst,clk;
output co;
output [6:0] led;
output [7:0] seg;
wire c,e;
wire [3:0] ms1,ms2,ms3,s1,s2,m1,m2,hr,bcd4;
CONTROL u1(clk,rst,sp,e);
CB10 u2(clk,c);
TIMER u3(c,rst,e,ms1,ms2,ms3,s1,s2,m1,m2,hr);
MUXL u4(clk,rst,e,ms1,ms2,ms3,s1,s2,m1,m2,hr,bcd4,seg);
BCD7 u5(bcd4,led);
assign co = c;
endmodule
文章作者: gzwangu
文章链接: https://gzwangu.github.io/2020/01/19/基于VHDL的数字秒表设计/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Clousbin の Blog
支付宝打赏
微信打赏