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,对应引脚直接拖进去就行。

 

 

### VHDL 数字时钟设计教程 #### 3.1 时钟分频电路的设计原则 时钟分频电路是数字系统设计的关键组件之一,在FPGA和ASIC中有广泛应用。通过设计计数器可以实现时钟分频功能,该过程涉及输入时钟、复位、使能信号、计数器以及分频系数等要素[^1]。 #### 3.2 计数器实现方式 为了达到所需的频率降低效果,通常采用二进制或模N计数器来完成这一任务。当计数值到达预设的最大值时,输出翻转一次,从而形成较低频率的新时钟信号。下面是一个简单的VHDL代码示例: ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Clock_Divider is Port ( clk_in : in STD_LOGIC; reset : in STD_LOGIC; enable : in STD_LOGIC; clk_out : out STD_LOGIC); end Clock_Divider; architecture Behavioral of Clock_Divider is signal count : integer := 0; constant max_count : integer := 50000000; -- 调整此参数可改变分频比例 begin process(clk_in,reset) begin if(reset='1')then count<=0; elsif(rising_edge(clk_in)) then if(enable='1')then if(count<max_count/2)then count<=count+1; clk_out<='0'; elsif(count>=max_count/2 and count<max_count)then count<=count+1; clk_out<='1'; else count<=0; end if; end if; end if; end process; end Behavioral; ``` 这段程序定义了一个基本的时钟分频模块,其中`clk_in`作为原始高频时钟源,而经过处理后的低频时钟则由`clk_out`提供给其他逻辑单元使用。此外还包含了同步清零(`reset`)与门控(`enable`)机制以增强灵活性。 #### 3.3 时序控制的重要性 在任何基于时钟的操作中,保持严格的时序关系是非常重要的。这不仅影响到系统的性能表现,更决定了整个硬件架构能否稳定运行。因此理解并正确运用时序概念——即让所有内部节点的动作都严格遵循同一个时间基准来进行——成为每位工程师必备的知识点[^2]。
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值