数字跑表实验报告(电子科技大学)
一 系统总体设计
设计要求
设计一个数字秒表,有6个输出显示,分别为百分之一秒、十分之一秒、秒、十秒、分、十分,系统主要由显示译码器、分频器、十进制计数器和六进制计数器组成。整个秒表还需有一个启动/停止信号和一个复位信号,以便秒表能随意停止及启动。 要求:
(1) 秒表计时范围为:1小时; (2) 秒表精度为0.01秒;
(3) 具有开始计时、停止计时控制功能,且开始计时、停止计时为一个复用按键; (4) 在正常计时显示过程中,能够在存储按键作用下存储某一计时时间;存储的时间组数为确定值或1至任意值;
(5) 在读取按键作用下存储的时间能够回放显示;回放显示时,秒表计时可停止或在后台正常进行;回放显示可手动或自动依次显示; (6) 具有复位功能;
(7) 用六位数码管显示时间读数。
系统工作原理
数字跑表通过系统将48MHz时钟进行分频得到100Hz的秒表时钟,之后通过对时钟信号进行计数得到具体的跑表显示数值,跑表数值作为显示单元电路的输入,显示单元控制数码管动态扫描显示计数
因此,系统主要划分为:分频器,计数器,显示控制,开始\\停在使能控制,清零控制,存储读取功能,按键消抖。 原理图如下:
二 单元电路设计
1.分频器
设计思路:输入信号48MHz,将其48000分频可得1KHz信号,再将1KHz信号10分频可得100Hz信号。1KHz用于显示LED扫描,100Hz用于计数器时钟。 源程序如下: library IEEE;
use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity pp is
PORT(CLKIN:IN STD_LOGIC; CLKOUT1K:OUT STD_LOGIC; CLKOUT100:OUT STD_LOGIC); end ENTITY pp;
architecture Behavioral of pp is
SIGNAL CNTER0:INTEGER RANGE 0 TO 23999 :=0; SIGNAL CNTER1:INTEGER RANGE 0 TO 4 :=0;
SIGNAL CLKOUT1K_TMP,CLKOUT100_TMP: STD_LOGIC:='0'; begin
PROCESS(CLKIN) IS BEGIN
IF CLKIN'EVENT AND CLKIN ='1' THEN IF CNTER0=23999 THEN CNTER0 <=0;
CLKOUT1K_TMP <= NOT CLKOUT1K_TMP; ELSE
CNTER0 <= CNTER0 + 1 ; END IF; END IF; END PROCESS;
CLKOUT1K <= CLKOUT1K_TMP; PROCESS(CLKOUT1K_TMP) IS BEGIN
IF CLKOUT1K_TMP'EVENT AND CLKOUT1K_TMP='1' THEN IF CNTER1 =4 THEN CNTER1 <=0;
CLKOUT100_TMP <= NOT CLKOUT100_TMP; ELSE CNTER1 <= CNTER1 + 1; END IF; END IF; END PROCESS;
CLKOUT100<=CLKOUT100_TMP; end Behavioral; 2.计数器以及清零装置
实验需要用到2个六进制计数器和4个十进制计数器,并且将六个计数器级联 十进制计数器的源程序: library IEEE;
use IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; entity COUNTER is
PORT(RST,CLK:IN STD_LOGIC; CARRY_IN:IN STD_LOGIC;
CARRY_OUT:OUT STD_LOGIC;
COUNT_OUT:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
end COUNTER;
architecture Behavioral of COUNTER is
SIGNAL COUNT:STD_LOGIC_VECTOR(3 DOWNTO 0):=\"0000\";
begin
PROCESS(RST,CLK) BEGIN
IF RST='1' THEN
COUNT<=\"0000\";
ELSIF CLK'EVENT AND CLK='1' THEN IF CARRY_IN='1' THEN
IF COUNT< \"1001\" THEN
COUNT <= COUNT + 1; ELSE
COUNT<=\"0000\"; END IF; ELSE NULL;
END IF; END IF;
END PROCESS;
COUNT_OUT<=COUNT;
CARRY_OUT<='1' WHEN CARRY_IN='1' AND COUNT=\"1001\"ELSE'0'; end Behavioral; 仿真结果:
六进制计数器的源程序为: library IEEE;
use IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; entity COUNTER2 is
PORT(RST,CLK:IN STD_LOGIC; CARRY_IN:IN STD_LOGIC;
CARRY_OUT:OUT STD_LOGIC;
COUNT_OUT:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
end COUNTER2;
architecture Behavioral of COUNTER2 is
SIGNAL COUNT:STD_LOGIC_VECTOR(3 DOWNTO 0):=\"0000\"; begin
PROCESS(RST,CLK) BEGIN
IF RST='1' THEN
COUNT<=\"0000\";
ELSIF CLK'EVENT AND CLK='1' THEN
IF CARRY_IN='1' THEN
IF COUNT< \"0101\" THEN
COUNT <= COUNT + 1; ELSE
COUNT<=\"0000\"; END IF; ELSE NULL;
END IF; END IF;
END PROCESS;
COUNT_OUT<=COUNT;
CARRY_OUT<='1' WHEN CARRY_IN='1' AND COUNT=\"0101\"ELSE'0';
end Behavioral; 仿真结果:
级联的源程序如下: entity COUNTER6 is
PORT(CSIGNAL:IN STD_LOGIC; CLEAR: IN STD_LOGIC; COUNT_EN:IN STD_LOGIC; RESULT1 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0); RESULT2 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
RESULT3 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0); RESULT4 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0); RESULT5 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0); RESULT6 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); end COUNTER6;
architecture Behavioral of COUNTER6 is COMPONENT COUNTER IS PORT(RST,CLK: IN STD_LOGIC; CARRY_IN: IN STD_LOGIC; CARRY_OUT: OUT STD_LOGIC; COUNT_OUT: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); END COMPONENT COUNTER; COMPONENT COUNTER2 IS PORT(RST,CLK: IN STD_LOGIC; CARRY_IN: IN STD_LOGIC; CARRY_OUT: OUT STD_LOGIC; COUNT_OUT: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); END COMPONENT COUNTER2; SIGNAL CARRY1,CARRY2,CARRY3,CARRY4,CARRY5,CARRY6:STD_LOGIC;
begin
U1:COUNTER PORT MAP(RST => CLEAR, CLK => CSIGNAL, CARRY_IN => COUNT_EN, CARRY_OUT => CARRY1, COUNT_OUT => RESULT1); U2:COUNTER PORT MAP(RST => CLEAR, CLK => CSIGNAL, CARRY_IN => CARRY1, CARRY_OUT => CARRY2, COUNT_OUT => RESULT2); U3:COUNTER PORT MAP(RST => CLEAR, CLK => CSIGNAL, CARRY_IN => CARRY2, CARRY_OUT => CARRY3, COUNT_OUT => RESULT3); U4:COUNTER2 PORT MAP(RST => CLEAR, CLK => CSIGNAL, CARRY_IN => CARRY3, CARRY_OUT => CARRY4, COUNT_OUT => RESULT4); U5:COUNTER PORT MAP(RST => CLEAR, CLK => CSIGNAL,
CARRY_IN => CARRY4, CARRY_OUT => CARRY5, COUNT_OUT => RESULT5); U6:COUNTER2 PORT MAP(RST => CLEAR, CLK => CSIGNAL, CARRY_IN => CARRY5, CARRY_OUT => CARRY6, COUNT_OUT => RESULT6); end Behavioral; 3.使能控制
按一下使能控制键,跑表开始计时,再次按下,跑表暂停计时,且计数器使能端高电平有效。因此程序设计思路为:最初提供一个低电平信号‘0’,按一下使能控制键时,信号翻转位‘1’,开始计时;当再次按下使能控制键时,信号再次翻转,变为‘0’,计时暂停。 源程序为: library IEEE;
use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL; entity EN is
Port ( S : in STD_LOGIC; E : out STD_LOGIC); end EN;
architecture Behavioral of EN is SIGNAL E1: STD_LOGIC;
begin
PROCESS(S) BEGIN
IF S'EVENT AND S='1' THEN E1<= NOT E1; END IF;
END PROCESS; E<=E1;
end Behavioral; 4.显示控制
显示控制模块应包含一个六进制计数器、3—8译码器、六选一数据选择器和七段译码器。六进制计数器的时钟信号频率为1KHZ,计数输出经过3-8译码后作为位选控制信号sel(7:0)。数据选择器的地址控制信号为计数输出,数据选择器的数据端为要显示的六位数据mh(3:0),ml(3:0),sh(3:0),sl(3:0),ds(3:0),cs(3:0)。根据地址控制信号选择其中一路输出至译码器,译码器的输出作为段选控制信号led(6:0)。根据硬件电路,需设置一个译码使能信号G,G为低电平有效。 源程序为:
entity multi is
port(clk:in std_logic;
f1,f2,f3,f4,f5,f6:in std_logic_vector(3 downto 0);
dig:out std_logic_vector(7 downto 0);
seg:out std_logic_vector(6 downto 0));
end multi;
architecture Behavioral of multi is
signal s:std_logic_vector(2 downto 0):=\"000\";
signal bcd:std_logic_vector(3 downto 0):=\"1000\";
begin
process(clk) --计数器
begin
if clk'event and clk='1' then
s<=s+1; end if; end process;
process(s,f1,f2,f3,f4,f5,f6)
begin case s is
when \"000\"=> bcd<=f1;
when \"001\"=> bcd<=f2; when \"010\"=> bcd<=\"1111\"; when \"011\"=> bcd<=f3; when \"100\"=> bcd<=f4; when \"101\"=> bcd<=\"1111\"; when \"110\"=> bcd<=f5; when \"111\"=> bcd<=f6; when others=> bcd<=\"1111\";
end case; end process;
process(s) begin
case s is
when \"000\"=> dig<=\"11111110\";
when \"001\"=> dig<=\"11111101\"; when \"010\"=> dig<=\"11111011\"; when \"011\"=> dig<=\"11110111\"; when \"100\"=> dig<=\"11101111\"; when \"101\"=> dig<=\"11011111\"; when \"110\"=> dig<=\"10111111\"; when others=> dig<=\"01111111\";
end case; end process;
process(bcd)
end Behavioral; 5.存储读取
begin case bcd is
when \"0000\"=> seg<=\"0000001\";
when \"0001\"=> seg<=\"1001111\"; when \"0010\"=> seg<=\"0010010\"; when \"0011\"=> seg<=\"0000110\"; when \"0100\"=> seg<=\"1001100\"; when \"0101\"=> seg<=\"0100100\"; when \"0110\"=> seg<=\"0100000\"; when \"0111\"=> seg<=\"0001111\"; when \"1000\"=> seg<=\"0000000\"; when \"1001\"=> seg<=\"0000100\"; when others=> seg<=\"1111110\";
end case;
end process;
设计思路:在计数器输出和显示器输入之间添加一个缓存装置,按下锁存键时,计数器的输出赋给一个临时变量,这时锁存控制装置的输出等于计数器的输出。而当按下读取键时,之前赋值的缓存就输入给显示装置,显示器显示的是之前锁存的数据。 源程序如下: entity choose is
port(split:in std_logic; 0);
output1,output2,output3,output4,output5,output6:out
input1,input2,input3,input4,input5,input6:in std_logic_vector(3 downto
std_logic_vector(3 downto 0)); end choose;
architecture Behavioral of choose is
signal cnt:std_logic_vector(2 downto 0):=\"000\";
signal a1,a2,a3,a4,a5,a6:std_logic_vector(3 downto 0); signal b1,b2,b3,b4,b5,b6:std_logic_vector(3 downto 0); signal c1,c2,c3,c4,c5,c6:std_logic_vector(3 downto 0); signal e1,e2,e3,e4,e5,e6:std_logic_vector(3 downto 0);
begin process(split) begin
if split'event and split='1' then if cnt=\"110\" then
cnt<=\"000\"; else
cnt<=cnt+1; end if;
end if;
end process;
process(cnt,input1,input2,input3,input4,input5,input6) begin case cnt is when\"000\"=>
a1<=input1;a2<=input2;a3<=input3;a4<=input4;a5<=input5;a6<=input6;c1<=input1;c2<=input2;c3<=input3;c4<=input4;c5<=input5;c6<=input6;
output1<=c1;output2<=c2;output3<=c3;output4<=c4;output5<=c5;output6<=c6;
when\"001\"=>
b1<=input1;b2<=input2;b3<=input3;b4<=input4;b5<=input5;b6<=input6;c1<=input1;c2<=input2;c3<=input3;c4<=input4;c5<=input5;c6<=input6;
output1<=c1;output2<=c2;output3<=c3;output4<=c4;output5<=c5;output6<=c6;
when\"010\"=>
e1<=input1;e2<=input2;e3<=input3;e4<=input4;e5<=input5;e6<=input6;c1<=input1;c2<=input2;c3<=input3;c4<=input4;c5<=input5;c6<=input6;
output1<=c1;output2<=c2;output3<=c3;output4<=c4;output5<=c5;output6<=c6;
when\"011\"=>
c1<=input1;c2<=input2;c3<=input3;c4<=input4;c5<=input5;c6<=input6;
output1<=c1;output2<=c2;output3<=c3;output4<=c4;output5<=c5;output6<=c6;
when\"100\"=>
output1<=a1;output2<=a2;output3<=a3;output4<=a4;output5<=a5;output6<=a6;
when\"101\"=>
output1<=b1;output2<=b2;output3<=b3;output4<=b4;output5<=b5;output6<=b6;
when\"110\"=>
output1<=e1;output2<=e2;output3<=e3;output4<=e4;output5<=e5;output6<=e6;
when others=>
c1<=input1;c2<=input2;c3<=input3;c4<=input4;c5<=input5;c6<=input6;
output1<=c1;output2<=c2;output3<=c3;output4<=c4;output5<=c5;output6<=c6; end case; end process;
end Behavioral;
6.按键消抖:对输入信号进行检测,当输入为高电平时开始计数,该高电平只有在保持一段时间不变(计数器达到一定值),才确认它为有效值;若持续时间不够计数器达到一定值,则判其无效并复位计数器。 entity e4 is
Port ( clk : in STD_LOGIC; sin : in STD_LOGIC; sout : out STD_LOGIC); end e4;
architecture Behavioral of e4 is signal cnt:integer range 1 to 20; begin process(clk) begin
if clk'event and clk='1' then if sin='0' then
sout<='0'; cnt<=1;
else if cnt=20 then sout<='1';
cnt<=1;
else
cnt<=cnt+1;
end if;
end if; end if; end process; end Behavioral;
三 设计实现
1.顶层设计
2.管脚分配
3.下载过程
(1) 光标移至【 Generate Programing File】后单击鼠标右键,然后单击【 Properties】 (2) 将Unused IOB Pins选为Pull Up方式 (3) 双击【 Generate Programing File】
(4) 双击【 Generate Prom, ACE,or JTAG File】 (5) 选择后缀为bit的文件,单击【 Open】,之后单击【 Bypass 】 (6) 右键,单击第一个选项,完成下载
四 测试结果及结论
经实验开发板实际测试,数字跑表运行正常,实现了设计要求,可以精确计时到0.01s,清零,使能端,锁存端,读取端均可对计时过程进行正确控制,也达到了按键消抖的预期目标。
因篇幅问题不能全部显示,请点此查看更多更全内容