【数字系统】基于VHDL语言设计电子时钟(Quartus II开发)

一、实验设计

设计一个电子时钟,要求能够完成时间的显示、复位、设置时间、整点报时的功能。采用VHDL语言写程序,使用Quartus II进行编程,最后在睿智四代AX4010板子上进行实验验证。

二、模块设计

按键消抖模块、时钟分频模块、置数模块、秒分时计数模块、蜂鸣器模块、数码管输出模块。

实现的功能:按键消抖、用户置数、时分秒计时显示、整点报时(n点钟n次)。

【数字系统】基于VHDL语言设计电子时钟(Quartus II开发)_第1张图片

三、模块代码

时钟分频模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity clk_sourse is
	port(
	clk:in std_logic;
	clk2:out std_logic;
	clk3:out std_logic
	);
	end clk_sourse;

architecture a of clk_sourse is
signal clk0:std_logic;
signal clk1:std_logic;
begin
	clk2<=clk1;
	clk3<=clk0;
	process(clk)
	variable cnt:integer range 0 to 50000000;
	variable cnt1:integer range 0 to 5000;
	begin
		if(clk'event and clk='1')then
		cnt:=cnt+1;
		cnt1:=cnt1+1;
			if(cnt=50000000)then
			clk1<=not clk1;
			cnt:=0;
			end if;
			if(cnt1=5000)then
			clk0<=not clk0;
			cnt1:=0;
			end if;
		end if;
	end process;
end a;

 秒计时模块

	LIBRARY IEEE;
	USE IEEE.STD_LOGIC_1164.ALL;
	USE IEEE.STD_LOGIC_ARITH.ALL;
	USE IEEE.STD_LOGIC_UNSIGNED.ALL;
	entity counter1 is
	port(
	clk:in std_logic;
	clr:in std_logic;
	key1:in std_logic;
	min:out std_logic;
	chg0:in std_logic_vector(3 downto 0);
	chg1:in std_logic_vector(3 downto 0);
	data0:out std_logic_vector(3 downto 0);
	data1:out std_logic_vector(3 downto 0)
	);
	end counter1;

architecture a of counter1 is
	signal cnt0:std_logic_vector(3 downto 0):="0000";
	signal cnt1:std_logic_vector(3 downto 0):="0000";

begin
	process(clk,clr,key1)
	begin
	if(clr='1' and key1='1')then
		if(clk'event and clk='1')then
			cnt0<=cnt0+1;
			if(cnt0=9)then
				cnt0<="0000";
				cnt1<=cnt1+1;
			end if;
			if(cnt1=5 and cnt0=9)then
				cnt0<="0000";
				cnt1<="0000";
				min<='1';
			else
				min<='0';
			end if;
		end if;
	elsif(clr='0' and key1='1')then
		cnt0<="0000";
		cnt1<="0000";
	elsif(key1='0' and clr='1')then
		cnt0<=chg0;
		cnt1<=chg1;
	else
	null;
	end if;
	data0<=cnt0;
	data1<=cnt1;
	end process;
end a;

 分计时模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
	
	entity counter2 is
	port(
	clk:in std_logic;
	clr,key1:in std_logic;--reset
	hour:out std_logic;
	chg2:in std_logic_vector(3 downto 0);
	chg3:in std_logic_vector(3 downto 0);
	data2:out std_logic_vector(3 downto 0);
	data3:out std_logic_vector(3 downto 0)
	);
	end counter2;

architecture a of counter2 is
	signal cnt0:std_logic_vector(3 downto 0):="0000";--9
	signal cnt1:std_logic_vector(3 downto 0):="0000";--1
begin
	process(clk,clr,key1)
	begin
	if(clr='1' and key1='1')then
		if(clk'event and clk='1')then
			cnt0<=cnt0+1;
			if(cnt0=9)then
				cnt0<="0000";
				cnt1<=cnt1+1;
			end if;
			if(cnt1=5 and cnt0=9)then
				cnt0<="0000";
				cnt1<="0000";
				hour<='1';
			else
				hour<='0';
			end if;
		end if;
	elsif(clr='0' and key1='1')then
		cnt0<="0000";
		cnt1<="0000";
		hour<='0';
	elsif(key1='0' and clr='1')then
		cnt0<=chg2;
		cnt1<=chg3;
	else 
	null;
	end if;
	data2<=cnt0;
	data3<=cnt1;
	end process;
end a;

 时计时模块

	LIBRARY IEEE;
	USE IEEE.STD_LOGIC_1164.ALL;
	USE IEEE.STD_LOGIC_ARITH.ALL;
	USE IEEE.STD_LOGIC_UNSIGNED.ALL;
	
	entity counter3 is
	port(
	clk:in std_logic;
	clr,key1:in std_logic;
	chg4,chg5:in std_logic_vector(3 downto 0);
	key2:in std_logic;
	data4:out std_logic_vector(3 downto 0);
	data5:out std_logic_vector(3 downto 0)
	);
	end counter3;

architecture a of counter3 is
	signal cnt0:std_logic_vector(3 downto 0):="0000";--hour gewei
	signal cnt1:std_logic_vector(3 downto 0):="0000";--hour shiwei
begin
	process(clk,clr,key1,key2)
	begin
	if(clr='1' and key1='1' and key2='1')then
		if(clk'event and clk='1')then
		cnt0<=cnt0+1;
		if(cnt0=9)then
			cnt0<="0000";
			cnt1<=cnt1+1;
		end if;
		if(cnt1=2 and cnt0=3)then
			cnt0<="0000";
			cnt1<="0000";
		end if;
		end if;
	elsif(clr='0' and key1='1' and key2='1')then
		cnt0<="0000";
		cnt1<="0000";
	elsif(key1='0' and key2='0' and clr='1')then
		cnt0<=chg4;
		cnt1<=chg5;
	else
	null;
	end if;	
		data4<=cnt0;--ge
		data5<=cnt1;--shi	
	end process;
end a;

 置数模块

	LIBRARY IEEE;
	USE IEEE.STD_LOGIC_1164.ALL;
	USE IEEE.STD_LOGIC_ARITH.ALL;
	USE IEEE.STD_LOGIC_UNSIGNED.ALL;
	
	entity chgclk is
	port(
	clk:in std_logic;
	key1,key2,clr:in std_logic;--add,mode
--	t:out std_logic_vector(1 downto 0);--testport
--	clk2:out std_logic;
	cdata0:out std_logic_vector(3 downto 0);
	cdata1:out std_logic_vector(3 downto 0);
	cdata2:out std_logic_vector(3 downto 0);
	cdata3:out std_logic_vector(3 downto 0);
	cdata4:out std_logic_vector(3 downto 0);
	cdata5:out std_logic_vector(3 downto 0)
	);
	end chgclk;

architecture a of chgclk is
	signal cnt0:std_logic_vector(3 downto 0):="0000";
	signal cnt1:std_logic_vector(3 downto 0):="0000";
	signal cnt2:std_logic_vector(3 downto 0):="0000";
	signal cnt3:std_logic_vector(3 downto 0):="0000";
	signal cnt4:std_logic_vector(3 downto 0):="0000";
	signal cnt5:std_logic_vector(3 downto 0):="0000";
	signal clk1:std_logic:='0';
begin
	process(clk)
	variable clkcnt:integer range 0 to 1000;--test
	begin
	if(clk'event and clk='1')then
		clkcnt:=clkcnt+1;
		if(clkcnt=1000)then--test
		clk1<=not clk1;
--		clk2<=clk1;--test
		clkcnt:=0;
		end if;
	end if;
	end process;
	
	process(clk1,key1,key2,clr)--change
	begin
	if(clr='1')then
		if(key1='0' and key2='1')then
			if(clk1'event and clk1='1')then
				cnt0<=cnt0+1;
				if(cnt0=9)then
					cnt0<="0000";
					cnt1<=cnt1+1;
				end if;
				if(cnt1=5 and cnt0=9)then
					cnt0<="0000";
					cnt1<="0000";
				end if;
			end if;
		cdata0<=cnt0;
		cdata1<=cnt1;
		elsif(key1='1' and key2='0')then
		if(clk1'event and clk1='1')then
				cnt2<=cnt2+1;
				if(cnt2=9)then
					cnt2<="0000";
					cnt3<=cnt3+1;
				end if;
				if(cnt3=5 and cnt2=9)then
					cnt2<="0000";
					cnt3<="0000";
				end if;
			end if;
		cdata2<=cnt2;
		cdata3<=cnt3;
		elsif(key1='0' and key2='0')then
		if(clk1'event and clk1='1')then
				cnt4<=cnt4+1;
				if(cnt4=9)then
					cnt4<="0000";
					cnt5<=cnt5+1;
				end if;
				if(cnt5=2 and cnt4=3)then
					cnt4<="0000";
					cnt5<="0000";
				end if;
			end if;
		cdata4<=cnt4;
		cdata5<=cnt5;
		else
		null;
		end if;
	else
	cnt0<="0000";
	cnt1<="0000";
	cnt2<="0000";
	cnt3<="0000";
	cnt4<="0000";
	cnt5<="0000";
	cdata0<="0000";
	cdata1<="0000";
	cdata2<="0000";
	cdata3<="0000";
	cdata4<="0000";
	cdata5<="0000";
	end if;
	end process;
end a;

按键消抖模块

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity unshake is
port(
     clk,reset_in,hc_show,next_key,add_key:in std_logic; --按键按下时为0
     reset_out,hc_out,next_out,add_out:out std_logic
	  );
end unshake;

architecture behav of unshake is

begin

process(clk,reset_in) 
  VARIABLE COUNT1 :INTEGER RANGE 0 TO 20000000; 
BEGIN 
if reset_in='0' then 
   if RISING_EDGE(clk) then
    if COUNT1<20000000 then COUNT1:=COUNT1+1; 
    else COUNT1:=COUNT1; 
	 end if; 
    if COUNT1<=19999999 then reset_out<='1'; 
    else reset_out<='0'; 
 	 end if; 
end if; 
else COUNT1:=0;
     reset_out<='1';
end if;
end process;

process(clk,hc_show) 
  VARIABLE COUNT2 :INTEGER RANGE 0 TO 20000000; 
BEGIN 
if hc_show='0' then 
   if RISING_EDGE(clk) then
    if COUNT2<20000000 then COUNT2:=COUNT2+1; 
    else COUNT2:=COUNT2; 
	 end if; 
    if COUNT2<=19999999 then hc_out<='1'; 
    else hc_out<='0'; 
 	 end if; 
end if;
else COUNT2:=0;
     hc_out<='1';
end if;
end process;

process(clk,next_key) 
  VARIABLE COUNT3 :INTEGER RANGE 0 TO 20000000; 
BEGIN 
if next_key='0' then 
   if RISING_EDGE(clk) then
    if COUNT3<20000000 then COUNT3:=COUNT3+1; 
    else COUNT3:=COUNT3; 
	 end if; 
    if COUNT3<=19999999 then next_out<='1'; 
    else next_out<='0'; 
 	 end if; 
end if; 
else COUNT3:=0;
     next_out<='1';
end if;
end process;

process(clk,add_key)
  VARIABLE COUNT4 :INTEGER RANGE 0 TO 20000000; 
begin
if add_key='0' then 
   if RISING_EDGE(clk) then
    if COUNT4<20000000 then COUNT4:=COUNT4+1; 
    else COUNT4:=COUNT4; 
	 end if; 
    if COUNT4<=19999999 then add_out<='1'; 
    else add_out<='0'; 
 	 end if; 
end if; 
else COUNT4:=0;
     add_out<='1';
end if;
end process;
end behav;

 蜂鸣器模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
	
entity baoshi is
	port(
	clk:in std_logic;--sec
   hourport:in std_logic;
	cnt1:in std_logic_vector(3 downto 0);--g
	cnt2:in std_logic_vector(3 downto 0);--s
	clk1:in std_logic;--clk
	bzz:out std_logic
	);
end baoshi;

architecture a of baoshi is
signal cnt01:std_logic_vector(3 downto 0):="0000";
signal cnt02:std_logic_vector(3 downto 0):="0000";
signal flag:std_logic:='0';
signal flag1:std_logic:='0';
begin
	process(clk,hourport)
	begin
		if( hourport='1' )then
			if(clk'event and clk='1')then
				if(flag='0')then
					if(NOT(cnt01>=cnt1) or NOT(cnt02>=cnt2))then
						cnt01<=cnt01+1;
						if(cnt01=9)then
							cnt01<="0000";
							cnt02<=cnt02+1;
						end if;
					end if;
				end if;
				flag<=not flag;
			end if;
		else
		cnt01<="0000";
		cnt02<="0000";
		end if;
	end process;
	
	process(clk1,hourport)
	begin
	if(hourport='1')then
		if(NOT((cnt01>=cnt1)and(cnt02>=cnt2)))then
			if(flag='1')then
				if(clk1'event and clk1='1')then
					if(flag1='1')then
						flag1<=not flag1;
						bzz<='1';
					else
						flag1<=not flag1;
						bzz<='0';
					end if;
				end if;
			else
				bzz<='0';
			end if;
		end if;
	end if;
	end process;
end a;

 数码管输出模块

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity scan_led is
port(
		clk,h_show:in std_logic;
		Fin_1:in std_logic_vector(3 downto 0);
		Fin_2:in std_logic_vector(3 downto 0);
		Fin_3:in std_logic_vector(3 downto 0);
		Fin_4:in std_logic_vector(3 downto 0);
		Fin_5:in std_logic_vector(3 downto 0);
		Fin_6:in std_logic_vector(3 downto 0);
		seg:out std_logic_vector(7 downto 0);
		data:buffer std_logic_vector(3 downto 0);
		scan:out std_logic_vector(3 downto 0)
		);
end;

architecture one of scan_led is
signal cnt4:integer range 0 to 3;
begin
	process(clk)
		begin
			if clk'event and clk='1' then
				cnt4<=cnt4+1;
			end if;
	end process;

	process(cnt4)
		begin
		if(h_show='1')then
			case cnt4 is
				when 0 =>scan<="1110";data<=Fin_3(3 downto 0);
				when 1 =>scan<="1101";data<=Fin_4(3 downto 0);
				when 2 =>scan<="1011";data<=Fin_1(3 downto 0);
				when 3 =>scan<="0111";data<=Fin_2(3 downto 0);
				when others=>null;
			end case;
		else
			case cnt4 is
				when 0 =>scan<="1110";data<=Fin_6(3 downto 0);
				when 1 =>scan<="1101";data<=Fin_5(3 downto 0);
				when 2 =>scan<="1111";data<="0000";
				when 3 =>scan<="1111";data<="0000";
				when others=>null;
			end case;
		end if;
	end process;

	process(data)
		begin
			case data(3 downto 0) is--编码部分
				when "0000"=>seg<="00000011";
				when "0001"=>seg<="10011111";
				when "0010"=>seg<="00100101";
				when "0011"=>seg<="00001101";
				when "0100"=>seg<="10011001";
				when "0101"=>seg<="01001001";
				when "0110"=>seg<="01000001";
				when "0111"=>seg<="00011111";
				when "1000"=>seg<="00000001";
				when "1001"=>seg<="00001001";
				when others=>null;
			end case;
	end process;
end;

四、管脚配置

【数字系统】基于VHDL语言设计电子时钟(Quartus II开发)_第2张图片

五、结语

由于实验板的不同,在系统的设计上也会有所差异。代码上可以借鉴——至少这套代码是跑得通的。可以借鉴的地方在于蜂鸣器的控制(整点报时功能的实现)、按键消抖实现的原理、译码管控制(数字输出)。然后结合自己的FPGA开发板具体接口可以做出自己的电子钟。

避坑ps:1.按钮输入需要确认有效电平的种类;2.译码输出模块需要配合管脚进行设置,因为管脚绑定可能是不一样的!

这个电子钟还有一些地方不够完善,可能还需要改进。所以,生搬这篇blog的代码是不太建议的。

 

你可能感兴趣的:(专业课)