VHDL数字时钟设计及引脚锁定方法

目录

引言

课设题目

时,分,秒模块

分频模块

按键去抖模块

调时模块

蜂鸣器报警模块

扫描信号输出模块

二进制转八段数码管显示信号

结果展示

小结


引言

        最近快期末考试周了,课设任务也随之而来。这个学期要完成FPGA的课程设计,题目有三个,为了弥补模电焊板子课设的遗憾这次我又选择了数字时钟的任务。经过两天硬肝,各方面找资料终于在上个礼拜六晚上两点钟完成了课设。今天休息而且好久没写博客就写篇文章总结一下吧!

课设题目

 

 可以看到,只需要完成正常的时间显示以及调时,分以及在特定的时间蜂鸣器发出响声即可。

时,分,秒模块

话不多说,直接先上代码

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity second is
port (clk,clr:in std_logic;
	  sec1,sec0:out  std_logic_vector(3 downto 0);
	co:out std_logic);
end second;
architecture sec of second is
SIGNAL cnt1,cnt0:std_logic_vector(3 downto 0);
begin
	process(clk)
	begin
	if(clr='1')then
	cnt0<="0000";
	cnt1<="0000";
	elsif(clk'event and clk='1')then
			if cnt1="0101" and cnt0="1001" then
				co<='1';
				cnt0<="0000";
				cnt1<="0000";
			elsif cnt0<"1001" then
				cnt0<=(cnt0+1);
			else 
			    cnt0<="0000";
				cnt1<=cnt1+1;
				co<='0';
			end if;
		end if;
	sec1<=cnt1;
	sec0<=cnt0;
	end process;
end sec;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity minute is
port (clk:in std_logic;
	  min1,min0:out std_logic_vector(3 downto 0);
	co:out std_logic);
end minute;
architecture min of minute is
SIGNAL cnt1,cnt0:std_logic_vector(3 downto 0);
begin
	process(clk)
	begin
	if(clk'event and clk='1')then
			if cnt1="0101" and cnt0="1001" then
				co<='1';
				cnt0<="0000";
				cnt1<="0000";
			elsif cnt0<"1001" then
				cnt0<=(cnt0+1);
			else 
			    cnt0<="0000";
				cnt1<=cnt1+1;
				co<='0';
			end if;
		end if;
	min1<=cnt1;
	min0<=cnt0;
	end process;
end min;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity hour is
port(clk,en:in std_logic;
h1,h0:out std_logic_vector(3 downto 0));
end hour;

architecture beha of hour is
signal cnt1,cnt0:std_logic_vector(3 downto 0);
begin
process(clk)
begin
if(clk'event and clk='1') then
if cnt1="0010" and cnt0="0011" then
cnt1<="0000";
cnt0<="0000";
elsif cnt0<"1001" then
cnt0<=cnt0+1;
else
cnt0<="0000";
cnt1<=cnt1+1;
end if;
end if;
h1<=cnt1;
h0<=cnt0;
end process;
end beha;

        上面分别是秒,分,时的代码。原理很简单,都是通过计数的方式,来一个时钟上升沿秒位就加一。当秒的低位到十了就进位给秒的高位,当秒的高位到六了就发出一个进位信号给分的地位。同理,分的高位以及时的低位和高位就设置好了。不同的是秒接分频后的时钟端,分接秒的进位信号,时接分的进位信号。

分频模块

library ieee; 
use ieee.std_logic_1164.all;  

entity fenpin is   
port (clk:in std_logic; 
		clk1: out std_logic;
		clk500: out std_logic;
		clk1000: out std_logic;
		clk16:out std_logic;
		clk256: out std_logic);                     
end fenpin; 

architecture fen_arc of fenpin is 
begin  
process(clk)  
variable cnt1: integer range 0 to 24999999;
variable cnt500: integer range 0 to 49999;  
variable cnt1000: integer range 0 to 24999;
variable cnt16: integer range 0 to 1669999; 
variable cnt256: integer range 0 to 99999;     
variable x: std_logic;
variable y: std_logic;  
variable z: std_logic;
variable m: std_logic;   
variable n: std_logic;       
begin   
	if clk'event and clk = '1' then    
		if cnt1<24999999 then     
			cnt1:=cnt1+1;    
		else     
			cnt1:=0;     
			x:= not x;    
		end if;  
	end if; 	
	clk1<=x;
	
	if clk'event and clk = '1' then    
		if cnt500<49999 then     
			cnt500:=cnt500+1;    
		else     
			cnt500:=0;     
			y:= not y;    
		end if;  
	end if; 	
	clk500<=y;
	
	if clk'event and clk = '1' then    
		if cnt1000<24999 then     
			cnt1000:=cnt1000+1;    
		else     
			cnt1000:=0;     
			z:= not z;    
		end if;  
	end if; 	
	clk1000<=z;
	
	if clk'event and clk = '1' then    
		if cnt16<1669999 then     
			cnt16:=cnt16+1;    
		else     
			cnt16:=0;     
			m:= not m;    
		end if;  
	end if; 	
	clk16<=m;
	
	if clk'event and clk = '1' then    
		if cnt256<99999 then     
			cnt256:=cnt256+1;    
		else     
			cnt256:=0;     
			n:= not n;    
		end if;  
	end if; 	
	clk256<=n;
	
	
	
end process; 
end fen_arc;

        数字时钟需要时钟信号的地方分别是秒的输入端,蜂鸣器的输入端,按键去抖电路,扫描显示电路。按照需要,分别分频出1Hz,500/1000Hz,256Hz,还有16Hz。(扫描好像是500Hz)。分频的方法也很简单,同样通过计数的方式可以达到分频的目的。

按键去抖模块

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity debounce is
port( clk,din: in std_logic;
		dout: out std_logic);
end debounce;
architecture behav of debounce is
signal counter:integer range 0 to 50000000;
signal df_1,df_2,df,rst_n:std_logic;
constant timer:integer:=5000;
begin


process(clk)
begin
if clk'event and clk='1' then
df_1<=din;
df_2<=df_1;
end if;
df<=df_1 xor df_2;
rst_n<=df;
end process;

process(clk,rst_n)
begin
if rst_n='1' then
counter<=0;
elsif clk'event and clk='1' then
counter<=counter+1;
if counter=50000000 then  
counter<=0;
end if;
if counter>=timer then
dout<=din;
end if;
end if;
end process;
end behav;

调时模块

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity ctrl is
port(clk:in std_logic;  --10HZ
key1,key2,key3:in std_logic;
led1,led2,led3:out std_logic);
end ctrl;
architecture a of ctrl is
begin
process (clk)
begin
if(clk'event and clk='1')then
if(key1='0')then
led1<='1';
elsif(key1='1')then
led1<='0';
end if;

if(key2='0')then
led2<='1';
elsif(key2='1')then
led2<='0';
end if;

if(key3='0')then
led3<='1';
elsif(key3='1')then
led3<='0';
end if;
end if;
end process;
end a;

蜂鸣器报警模块

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity xiang is
port(m1,m0,s1,s0:in std_logic_vector(3 downto 0);
  clk1,clk2:in std_logic;
    speaker:out std_logic);
end xiang;
architecture sss_arc of xiang is
  begin
  process(clk1,clk2,m1,m0,s1,s0)
  begin
    speaker <= '0';
if(m1="0101"and m0="1001"and s1="0101"and s0="1001")then
speaker<=clk2;--1024HZ
else 
  speaker <= '1';
end if;
if(m1="0101"and m0="1001")then 
  if(s1="0101" )then
   if(s0="0000" or s0="0010" or s0="0100" or s0="0110" or s0="1010")then
  speaker<=clk1;--512HZ
   end if;
  end if;
else
  speaker <= '1';
end if;
end process;
end sss_arc;

扫描信号输出模块

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

entity saomiao is
    port(
    clk500:in std_logic;--------------------------------时钟信号
    cnt1:buffer integer);
    end saomiao;

architecture one of saomiao is
begin
process(clk500)-------主要是让计算两个数码管的数值
begin
        if clk500'event and clk500 = '1' then
        if cnt1 = 5 then cnt1 <= 0;
        else
        cnt1 <= cnt1+1;
        end if;
        end if;
end process;
end one;
        

我这里主要是产生0-5的扫描信号,最后赋值给DigitalClock.vhd的扫描模块达到扫描的目的。扫描模块代码如下:

case cn1 is
        when 0 => s <= h_1; q <="011111";------------cnt扫描信号,q位选信号,s数码管显示。
        when 1 => s <= h_0; q <="101111";

        when 2 => s <= min_1; q <="110111";
        when 3 => s <= min_0; q <="111011";

        when 4 => s <= sec_1; q <="111101";
        when 5 => s <= sec_0; q <="111110";
        when others => null;
        
    end case;   

二进制转八段数码管显示信号

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

entity f2e is
    port(
    clk:in std_logic;
    high,low:in std_logic_vector(3 downto 0);--------------------------------时钟信号
    num1,num0:out std_logic_vector(7 downto 0));
end f2e;

architecture beh of f2e is
begin
    process(clk,high,low)
    begin
        case high is
            when ("0000")=> num1 <= "11000000";
            when ("0001")=> num1 <= "11111001";
            when ("0010")=> num1 <= "10100100";
            when ("0011")=> num1 <= "10110000";
            when ("0100")=> num1 <= "10011001";
            when ("0101")=> num1 <= "10010010";
            when ("0110")=> num1 <= "10000010";
            when ("0111")=> num1 <= "11111000";
            when ("1000")=> num1 <= "10000000";
            when ("1001")=> num1 <= "10010000";
            when others=> num1 <= null;
        end case;

        case low is
            when "0000"=> num0 <= "11000000";
            when "0001"=> num0 <= "11111001";
            when "0010"=> num0 <= "10100100";
            when "0011"=> num0 <= "10110000";
            when "0100"=> num0 <= "10011001";
            when "0101"=> num0 <= "10010010";
            when "0110"=> num0 <= "10000010";
            when "0111"=> num0 <= "11111000";
            when "1000"=> num0 <= "10000000";
            when "1001"=> num0 <= "10010000";
            when others=> num0 <= null;
        end case;
    end process;
end beh;

这个代码主要是把之前时钟输出的二进制数转为八段数码管相对应显示的字符。

结果展示

(woc,半夜两点的风吹的那个冷啊!)

小结

        使用的芯片型号是Cyclone IV E  EP4CE6F17C8,最后实现了数字时钟的显示,调时,以及特定时间报警。完成课设的要求。需要最后的工程文件或者sof文件可以私信获取。

Tips:引脚绑定方法——Pin Planner,对应引脚直接拖进去就行。

 

猜你喜欢

转载自blog.csdn.net/weixin_47666981/article/details/121728451