数字时钟(秒表)
秒表是人们日常生活中常用的测时仪器,它能够简单的完成计时、清零等功能,从一年一度的校际运动会到NBA、世界杯、奥运会,都能看到秒表的身影。请详细分析秒表的计时策略和实现方法,给出相应的设计方案和仿真结果。 一、 系统设计要求
设计一块数字秒表,能够精确反映计时时间,并完成复位、计时功能。
秒表计时的最大范围为1小时,精度为0.01秒。秒表可得到计时时间的分、秒、0.1秒等度量,且各度量单位间可正确进位。
当复位清零有效时,秒表清零并做好计时准备。任何情况下,只要按下复位开关,秒表都要无条件的进行复位操作,即使在计时过程中也要无条件的清零。
设置秒表启动/停止开关。按下该开关,秒表即刻开始计时,并得到计时结果;放开开关时,计时停止。
二、 系统设计方案
根据上述设计要求,可以预先设计若干个不同进制的计数器单元模块,然后将其进行例化组合来得到数字秒表系统。
要满足数字秒表的精度,首先要获得精确的计时基准信号,这里的系统精度要求为0.01秒,因此必须设置周期为0.01秒的时钟脉冲。
1/100秒、秒、分等计时单位之间的进位转换可以通过不同进制的计数器实现,我们分别设计十进制计数器和六进制计数器,每位计数器均能输出相应计时单位计数结果,其中,十进制计数器可以实现以0.01秒、0.1秒、1秒和1分为单位的计数,六进制计数器可以实现以10秒、10分为单位的计数,把各级计数器级联,即可同时显示百分秒、秒和分钟。
停止和启动功能可以通过计时使能信号完成。信号有效时正常计时,否则没有脉冲输入到计数器,从而停止计时。因为一旦按下复位清零开关数字秒表就无条件清零,因此其优先级必须高于计时使能信号。
数字秒表的系统框图如下图所示。Clk0是周期为0.01秒的时钟脉冲,clr0为复位清零信号,en为计时使能信号,dataout[23…0]为输出信号,以不同的时钟周期为单位的计数器对所应的输入信号如下表所示。
stopwatchclk0clr0eninstDataout[23...0]
计数单位及对应的输出信号 对应的输出信号 0.01秒 0.1秒 1秒 10秒 1分 10分 计数时钟周期 Dataout[3…0] Dataout[7…4] Dataout[11…8] Dataout[15…12] Dataout[19…16] Dataout[23…20] 三、 VHDL编程
数字秒表的实现主要依赖于两个计数器模块的设计:十进制计数器和六进制计数器。 在这两个计数器中,除了计数的进制不同之外,其余输入和输出信号均有相同的含义。
十进制计数器模块的VHDL实现如下: Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY cnt10 IS
PORT ( clk : IN STD_LOGIC;
clr: IN STD_LOGIC; --复位信号
ena: IN STD_LOGIC; --计数使能信号
q: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --计数输出信号,输出计数器当前的值
co: OUT STD_LOGIC --进位输出信号,当计数器满时,产生进位 );
END ENTITY cnt10;
ARCHITECTURE rtl OF cnt10 IS
SIGNAL tmp: STD_LOGIC_VECTOR(3 DOWNTO 0); --定义计数器
BEGIN
PROCESS ( CLK, clr, ena) --当敏感信号发生变化时,启动计数进程 BEGIN
IF clr ='1' THEN --如果清零信号为有效
tmp<=”0000”; --任何时刻均将计数器清零 ELSIF (rising_edge(clk)) then
IF (ena='1') THEN --计数器计数 IF (tmp=”1001”) THEN --计数器满
tmp<=”0000”;
ELSE
tmp<=tmp+‘1’; --计数器加1
end if;
END IF; END IF; END PROCESS;
PROCESS (tmp) --当计数器发生变化时,启动输出进程 BEGIN
IF(tmp=”0000”) then --当计数器状态为0时 co<='1'; --进位输出信号有效
else
co<=’0’; --否则为0
END if; END PROCESS;
q<=tmp; --输出计数器的值 END rtl;
六进制计数器模块的VHDL实现如下:(与十进制计数器模块类似) Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY cnt6 IS
PORT ( clk : IN STD_LOGIC;
clr: IN STD_LOGIC; --复位信号
ena: IN STD_LOGIC; --计数使能信号
q: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --计数输出信号,输出计数器当前的值
co: OUT STD_LOGIC --进位输出信号,当计数器满时,产生进位 );
END ENTITY cnt6;
ARCHITECTURE rtl OF cnt6 IS
SIGNAL tmp: STD_LOGIC_VECTOR(3 DOWNTO 0); --定义计数器 BEGIN
PROCESS ( CLK, clr, ena) --当敏感信号发生变化时,启动计数进程 BEGIN
IF clr ='1' THEN --如果清零信号为有效
tmp<=”0000”; --任何时刻均将计数器清零 ELSIF (rising_edge(clk)) then
IF (ena='1') THEN --计数器计数 IF (tmp=”1001”) THEN --计数器满
tmp<=”0000”;
ELSE
tmp<=tmp+‘1’; --计数器加1
end if;
END IF; END IF; END PROCESS;
PROCESS (tmp) --当计数器发生变化时,启动输出进程 BEGIN
IF(tmp=”0000”) then --当计数器状态为0时 co<='1'; --进位输出信号有效
else
co<=’0’; --否则为0
END if;
END PROCESS;
q<=tmp; --输出计数器的值 END rtl;
数字秒表顶层模块的VHDL实现如下: Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY stopwatch IS
PORT ( clk0 : IN STD_LOGIC;
clr0: IN STD_LOGIC; --复位信号
en: IN STD_LOGIC; --计数使能信号
dataout: OUT STD_LOGIC_VECTOR(23 DOWNTO 0) );
END ENTITY stopwatch;
ARCHITECTURE rtl OF stopwatch IS Component cnt6 is --定义六进制计数器元件
PORT ( clk : IN STD_LOGIC; clr: IN STD_LOGIC;
ena: IN STD_LOGIC;
q: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
co: OUT STD_LOGIC );
End Component cnt6;
Component cnt10 is --定义十进制计数器元件
PORT ( clk : IN STD_LOGIC; clr: IN STD_LOGIC;
ena: IN STD_LOGIC;
q: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
co: OUT STD_LOGIC );
End Component cnt10;
--输出计数结果
Signal co1: STD_LOGIC; --定义计数器元件的进位输出信号 Signal co2: STD_LOGIC; Signal co3: STD_LOGIC; Signal co4: STD_LOGIC; Signal co5: STD_LOGIC;
BEGIN --元件例化语句,通过计数器的级联实现数字秒表
U1: cnt10 port map(clk0,clr0,en,dataout(3 downto 0), co1); U2: cnt10 port map(co1,clr0,en,dataout(7 downto 4), co2); U3: cnt10 port map(co2,clr0,en,dataout(11 downto 8), co3); U4: cnt6 port map(co3,clr0,en,dataout(15 downto 12), co4); U5: cnt10 port map(co4,clr0,en,dataout(19 downto 16), co5); U6: cnt6 port map(co5,clr0,en,dataout(23 downto 20)); END rtl;
四、 实验小结
本实验采用模块例化和级联的方法,实现了一个具有计时、复位功能的数字秒表。在系统设计的过程中,先后定义了两个计数器电路模块,并在顶层模块中对这两个子模块进行了元件例化。通过本实验的学习,应该能够十分熟练地实现任意进制计数器电路,并对元件的例化使用方法有更加深刻的理解。
因篇幅问题不能全部显示,请点此查看更多更全内容