本文为大家介绍电子计时器的VHDL设计方法。
设计一个电子计时器,给定时钟信号为512HZ,要求系统达到以下功能:
(1)用6个数码管分别显示时、分、秒,计时范围为00:00:00~23:59:59。
(2)计时精度是1s。
(3)具有启/ 停开关, 复位开关。
总体方框图
本系统由六十进制计数器模块、二十四进制计数器模块、分频模块执行计时功能, 输入信号是512Hz,通过分频后为1Hz,时钟信号是1Hz作为计时器的秒输入,秒为60进制计数器,分也为60进制计数器,小时采用二十四进制计数器, 各级进位作为高位的使能控制。
设计一个八位的六十进制计数器模块,输入信号为en、reset、clk,分别为使能、复位和时钟信号,输出信号为qa[3„0]、qb[3„0]、rco,分别为低4位输出、高4位输出和进位位。
六十进制计数器
秒计数器的仿真波形图
利用60进制计数器完成00到59的循环计数功能,当秒计数至59时,再来一个时钟脉冲则产生进位输出,即enmin=1;reset作为复位信号低电平有效,即高电平时正常循环计数,低电平清零。因为这种60进制的VHDL语言是很好写的,它并不复杂,再说我们必须要学会这些基本的硬件语言的描写。
分钟计数器的仿真波形图
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
ENTITY count60 IS
PORT( en,Reset,clk: in STD_LOGIC;
qa: out STD_LOGIC_VECTOR(3 DOWNTO 0);
qb: out STD_LOGIC_VECTOR(3 DOWNTO 0);
rco: OUT STD_LOGIC); END count60;
ARCHITECTURE a OF count60 IS
BEGIN
process(clk)
variable tma: STD_LOGIC_VECTOR(3 DOWNTO 0);
variable tmb: STD_LOGIC_VECTOR(3 DOWNTO 0); begin
If Reset =‘0’then tma:=“0000”;
tmb:=“0000”;
elsif clk‘event and clk=’1‘ then
if en=’1‘ then
rco<=tmb(2)and tmb(0)and tma(3)and tma(0);
if tma=“1001” then
tma:=“0000”;
if tmb=“0101” then
tmb:=“0000”;
else tmb:=tmb+1;
end if;
else tma:=tma+1;
end if;
end if;
end if;
qa<=tma;qb<=tmb; end process; END a;
设计一个八位的二十四进制计数器模块,输入信号为en、reset、clk,分别为使能、复位和时钟信号,输出信号为qa[3„0]、qb[3„0],分别为低4位输出、高4位输出。
二十四进制计数器示意图
小时计数器的仿真波形图
小时计数模块利用24进制计数器,通过分钟的进位信号的输入可实现从00到23的循环计数。
该模块部分VHDL 源程序如下:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
ENTITY count24 IS
PORT( en,Reset,clk: in STD_LOGIC;
qa: out STD_LOGIC_VECTOR(3 DOWNTO 0);
qb: out STD_LOGIC_VECTOR(3 DOWNTO 0));
END count24;
ARCHITECTURE a1 OF count24 IS
BEGIN
process(clk)
variable tma: STD_LOGIC_VECTOR(3 DOWNTO 0);
variable tmb: STD_LOGIC_VECTOR(3 DOWNTO 0);
begin
If Reset = ‘0’then tma:=“0000”;
tmb:=“0000”; else
if clk‘event and clk=’1‘ then
if en=’1‘ then
if tma=“1001” then
tma:=“0000”;
tmb:=tmb+1;
elsif tmb=“0010” and tma=“0011” then
tma:=“0000”;
tmb:=“0000”;
else tma:=tma+1;
end if;
end if;
end if;
end if;
qa<=tma;
qb<=tmb;
end process;
END a1;
设计一个分频器,要求将输入512HZ的时钟信号分频为1HZ的时钟信号作为计时器的秒输入。输入信号为clk和rst,分别为时钟信号和复位信号,输出信号为clk_out,为分频器1HZ的时钟信号输出。
分频器示意图
该模块部分VHDL 源程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY fenpinqi IS
PORT (CLK,RST:in std_logic;
CLK_OUT:out std_logic);
END fenpinqi;
ARCHITECTURE behav OF fenpinqi IS
signal clk_data:std_logic;
SIGNAL CNT6 :
INTEGER := 0;
BEGIN
PROCESS(CLK)
BEGIN
IF RST = ‘0’ THEN CNT6<=0
ELSIF CLK‘EVENT AND CLK=’1‘ THEN
IF CNT6=255 THEN
clk_data<=NOT clk_data;
CNT6<=0;
ELSE CNT6<=CNT6+1;
END IF;
END IF;
CLK_OUT<=clk_data;
END PROCESS;
END behav;
LED有着显示亮度高,响应速度快的特点,最常用的是七段式LED显示器,又称数码管。七段LED显示器内部由七个条形发光二极管和一个小圆点发光二极管组成,根据各管的亮暗组合成字符。
LED数码管的g~a七个发光二极管因加正电压而发亮,因加零电压而不能发亮,不同亮暗的组合就能形成不同的字形,这种组合称之为字形码(段码),如显示”0”,字形码为3fh。
LED数码管结构图
数码管的接口有静态接口和动态接口。动态接口采用各数码管循环轮流显示的方法,当循环显示频率较高时,利用人眼的暂留特性,看不出闪烁显示现象,这种显示需要一个接口完成字形码的输出(字形选择),另一接口完成各数码管的轮流点亮(数位选择)。
将二十四进制计数器和2个六十进制计数器的输出作为LED显示模块的输入,在时钟信号的控制下通过此模块完成6个LED数码管的显示,输出信号为WEI[2…0]和LED[6…0],分别为位选信号和段码输出。
LED显示示意图
该模块部分VHDL 源程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY clock1 IS
PORT(CLK: IN STD_LOGIC;
S1, S2, S3, S4, S5, S6: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
WEI: OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
LED: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END ENTITY;
ARCHITECTURE behave OF clock1 IS
SIGNAL CNT6 : INTEGER RANGE 0 TO 5 := 0;
SIGNAL SHUJU: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PRO1:PROCESS(CLK)
BEGIN
IF CLK‘EVENT AND CLK = ’1‘ THEN
CNT6 <= CNT6 + 1;
CASE CNT6 IS
WHEN 0 => WEI <= “000”; SHUJU <= S1;
WHEN 1 => WEI <= “001”; SHUJU <= S2;
WHEN 2 => WEI <= “010”; SHUJU <= S3;
WHEN 3 => WEI <= “011”; SHUJU <= S4;
WHEN 4 => WEI <= “100”; SHUJU <= S5;
WHEN 5 => WEI <= “101”; SHUJU <= S6;
CNT6<=0;
WHEN OTHERS => NULL;
END CASE;
END IF;
END PROCESS;
PRO2: PROCESS(SHUJU)
BEGIN
CASE SHUJU IS
WHEN “0000” => LED<= “1111110”
WHEN “0001” => LED<= “0110000”
WHEN “0010” => LED<= “1101101”
WHEN “0011” => LED<= “1111001”
WHEN “0100” => LED<= “0110011”
WHEN “0101” => LED<= “1011011”
WHEN “0110” => LED<= “1011111”
WHEN “0111” => LED<= “1110000”
WHEN “1000” => LED<= “1111111”
WHEN “1001” => LED<= “1111011”
WHEN others=> LED<= “0000000”
END CASE;
END PROCESS;
END
通过上面的分频器,两个60进制的计数器,一个12/24进制的计数器,6选1扫描器,7段数码显示器,设计如图所示的顶层。规定每一模块的功能和各模块之间的接口。同时整个计数器有清零。 设计思想,利用脉冲时钟产生一个1Hz的信号来实现一秒钟的控制,要产生1Hz的信号就要用到分频器,实验中用512分频器把512Hz的信号变成1Hz。然后信号进入控制秒的计数器,当第60个脉冲时钟到来时,产生一个进位信号, 送到控制分的计数器,同理,当第60个脉冲时钟到来时,产生一个进位信号,送到控制小时的计数器。当小时计数器计数到12/24时,完成一个周期,跳转到零。输出是由动态扫描器来完成的。扫描器时钟取至前面分频未结束时的一个512Hz的信号。这样就能够在7段数码显示管上,以512Hz的频率扫描显示出时钟的数字变化。
通过元件例化将各个模块连接起来,组成一个整体。
元件例化就是将预先设计好的设计实体定义为一个元件,然后利用特定的语句将此元件与当前的设计实体中的指定端口相连接,从而为当前设计实体引入一个新的低一级的设计层次。所定义的例化元件相当于一个要插在这个电路系统板上的芯片,而当前设计实体中指定的端口则相当于这块电路板上准备接受此芯片的一个插座。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;
entity dzjsq is
port(en,clk,reset:in std_logic;
wei:out std_logic_vector(2 downto 0);
led:out std_logic_vector(7 downto 0));
end entity dzjsq;
architecture abc of dzjsq is
component count60
PORT( en,Reset,clk: in STD_LOGIC;
qa: out STD_LOGIC_VECTOR(3 DOWNTO 0);
qb: out STD_LOGIC_VECTOR(3 DOWNTO 0);
rco: OUT STD_LOGIC);
end component;
component count24
PORT( en,Reset,clk: in STD_LOGIC;
qa: out STD_LOGIC_VECTOR(3 DOWNTO 0);
qb: out STD_LOGIC_VECTOR(3 DOWNTO 0));
end component; component fenpinqi
PORT (CLK,RST:in std_logic; CLK_OUT:out std_logic);
end component; component clock1
PORT(CLK: IN STD_LOGIC;
S1, S2, S3, S4, S5, S6: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
WEI: OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
LED: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
end component;
signal a1,a2,a3,a4,a5,a6:std_logic_vector(3 downto 0);
signal b1,b2,b3: std_logic; begin
u1: fenpinqi port map(clk,reset,b1);
u2:count60 port map(en,reset,b1,a1,a2,b2);
u3:count60 port map(en,reset,b2,a3,a4,b3);
u4:count24 port map(en,reset,b3,a5,a6);
u5:clock1 port map(clk,a1,a2,a3,a4,a5,a6,wei,led);
end architecture abc;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
ENTITY count60 IS
PORT( en,Reset,clk: in STD_LOGIC;
qa: out STD_LOGIC_VECTOR(3 DOWNTO 0);
qb: out STD_LOGIC_VECTOR(3 DOWNTO 0);
rco: OUT STD_LOGIC);
END count60;
ARCHITECTURE a OF count60 IS
BEGIN
process(clk)
variable tma: STD_LOGIC_VECTOR(3 DOWNTO 0);
variable tmb: STD_LOGIC_VECTOR(3 DOWNTO 0);
begin
If Reset =‘0’then tma:=“0000”;
tmb:=“0000”;
elsif clk‘event and clk=’1‘ then
if en=’1‘ then
rco<=tmb(2)and tmb(0)and tma(3)and tma(0);
if tma=“1001” then
tma:=“0000”;
if tmb=“0101” then
tmb:=“0000”;
else tmb:=tmb+1;
end if;
else tma:=tma+1;
end if;
end if;
end if;
qa<=tma;
qb<=tmb;
end process;
END a;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
ENTITY count24 IS
PORT( en,Reset,clk: in STD_LOGIC;
qa: out STD_LOGIC_VECTOR(3 DOWNTO 0);
qb: out STD_LOGIC_VECTOR(3 DOWNTO 0));
END count24;
ARCHITECTURE a1 OF count24 IS
BEGIN
process(clk)
variable tma: STD_LOGIC_VECTOR(3 DOWNTO 0);
variable tmb: STD_LOGIC_VECTOR(3 DOWNTO 0);
begin
If Reset = ‘0’then tma:=“0000”;
tmb:=“0000”;
else if clk‘event and clk=’1‘ then
if en=’1‘ then
if tma=“1001” then
tma:=“0000”;
tmb:=tmb+1;
elsif tmb=“0010” and tma=“0011” then
tma:=“0000”;
tmb:=“0000”;
else tma:=tma+1;
end if;
end if;
end if;
end if;
qa<=tma;
qb<=tmb;
end process;
END a1; LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY fenpinqi IS
PORT (CLK,RST:in std_logic;
CLK_OUT:out std_logic);
END fenpinqi;
ARCHITECTURE behav OF fenpinqi IS signal clk_data:std_logic;
SIGNAL CNT6 : INTEGER := 0;
BEGIN
PROCESS(CLK) BEGIN
IF RST = ‘0’ THEN
CNT6<=0
ELSIF CLK‘EVENT AND CLK=’1‘ THEN
IF CNT6=512 THEN
clk_data<=NOT clk_data;
CNT6<=0;
ELSE CNT6<=CNT6+1;
END IF;
END IF;
CLK_OUT<=clk_data;
END PROCESS;
END behav;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY clock1 IS
PORT(CLK: IN STD_LOGIC;
S1, S2, S3, S4, S5, S6: IN STD_LOGIC_VECTOR(3 DOWNTO 0); WEI: OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
LED: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY;
ARCHITECTURE behave OF clock1 IS SIGNAL CNT6 : INTEGER RANGE 0 TO 5 := 0;
SIGNAL SHUJU: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN PRO1:PROCESS(CLK)
BEGIN
IF CLK‘EVENT AND CLK = ’1‘ THEN
CNT6 <= CNT6 + 1;
CASE CNT6 IS
WHEN 0 => WEI <= “000”;
SHUJU <= S1; WHEN 1 => WEI <= “001”;
SHUJU <= S2; WHEN 2 => WEI <= “010”;
SHUJU <= S3; WHEN 3 => WEI <= “011”;
SHUJU <= S4; WHEN 4 => WEI <= “100”;
SHUJU <= S5;
WHEN 5 => WEI <= “101”;
SHUJU <= S6;
CNT6<=0;
WHEN OTHERS => NULL;
END CASE;
END IF;
END PROCESS;
PRO2: PROCESS(SHUJU)
BEGIN CASE SHUJU IS WHEN “0000” => LED<= x“3f”
WHEN “0001” => LED<= x“06”
WHEN “0010” => LED<= x“5b”
WHEN “0011” => LED<= x“4f”
WHEN “0100” => LED<= x“66”
WHEN “0101” => LED<= x“6d”
WHEN “0110” => LED<= x“7d”
WHEN “0111” => LED<= x“07”
WHEN “1000” => LED<= x“7f”
WHEN “1001” => LED<= x“6f”
WHEN others=> LED<= x“00”
END CASE;
END PROCESS;
END
全部0条评论
快来发表一下你的评论吧 !