VHDL设计时钟,产生时分秒信号并用数码管显示

(好长时间没学习了,写篇文章来开始我的学习模式,找一下状态)
进入正题

简介
本文主要介绍如何用VHDL设计一个时钟(可以产生时分秒的信号),然后用数码管显示出时分秒。

实验器材: FPGA开发板、板载6位数码管(共阳极)

设计思路

设计两个模块,一个模块负责产生时分秒的信号,另一个模块负责驱动数码管显示出时分秒的时间。然后在顶层模块中把两个模块的输入输出进行例化。(本文只给出底层模块的VHDL程序,顶层模块进行例化就可以了)

原理介绍

时钟:通过计数FPGA开发板自带的40MHZ时钟的脉冲个数来产生秒数。得到秒数之后就可以得到分钟数,小时数。(计算可得40,000,000个脉冲大概为1秒)
数码管:数码管需要实现动态显示(各位数码管可以“同时”显示不同的数字)。实现方法就是驱动第一位显示要显示的数字,几毫秒过后在驱动第二位显示要显示的数字,几毫秒后再驱动第三位显示要显示的数字,,,一直到第六位。然后不断循环显示。这样人眼看到的效果就是同时显示了不同的数字。

VHDL程序

时钟

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

entity timer is
port(
	rst_n,clk:in std_logic;
	hour:buffer std_logic_vector(4 downto 0);
	minute,second:buffer std_logic_vector(5 downto 0);
	up,down,sel,clear_s:in std_logic
	);
end timer;

architecture bev of timer is
begin
	process(rst_n,clk)
		variable count1:integer range 0 to 20000;
		variable count2:integer range 0 to 2000;
	begin
		if rst_n='0' then
			hour<="00000";
			minute<="000000";
			second<="000000";
			count1:=0;
			count2:=0;
		elsif clk'event and clk='1' then
			count1:=count1+1;
			if count1=20000 then
				count1:=0;
				count2:=count2+1;
				if count2=2000 then  --2000为1秒
					count2:=0;
					second<=second+1;
					if to_integer(unsigned(second))=59 then 
						second<=std_logic_vector(to_unsigned(0,6));
						minute<=minute+1;
						if to_integer(unsigned(minute))=59 then
							minute<=std_logic_vector(to_unsigned(0,6));
							hour<=hour+1;
							if to_integer(unsigned(hour))=23 then
								hour<=std_logic_vector(to_unsigned(0,5));
							end if;
						end if;
					end if;
				end if;
			end if;
		end if;
	end process;
end bev;

数码管

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

entity smg_display is
port(
	rst_n: in std_logic;
	clk: in std_logic;
	DIG:out std_logic_vector(7 downto 0);
	SEL:out std_logic_vector(5 downto 0);
	hour:in std_logic_vector(4 downto 0);
	minute,second:in std_logic_vector(5 downto 0)
	);
end smg_display;

architecture bev of smg_display is
	constant NUM0: std_logic_vector:="11000000";
	constant NUM1: std_logic_vector:="11111001";
	constant NUM2: std_logic_vector:="10100100";
	constant NUM3: std_logic_vector:="10110000";
	constant NUM4: std_logic_vector:="10011001";
	constant NUM5: std_logic_vector:="10010010";
	constant NUM6: std_logic_vector:="10000010";
	constant NUM7: std_logic_vector:="11111000";
	constant NUM8: std_logic_vector:="10000000";
	constant NUM9: std_logic_vector:="10010000";
	constant NUM_NULL: std_logic_vector:="11111111";
	
	constant SEL1: std_logic_vector:="111110";
	constant SEL2: std_logic_vector:="111101";
	constant SEL3: std_logic_vector:="111011";
	constant SEL4: std_logic_vector:="110111";
	constant SEL5: std_logic_vector:="101111";
	constant SEL6: std_logic_vector:="011111";
	constant SEL_NULL: std_logic_vector:="111111";
	
	signal command: integer range 0 to 6;
	signal num: integer range 0 to 9;
begin
	with command select
		num <= to_integer(unsigned(hour)) /10 when 1,
		       to_integer(unsigned(hour)) rem 10 when 2,
				 to_integer(unsigned(minute)) /10 when 3,
		       to_integer(unsigned(minute)) rem 10 when 4,
				 to_integer(unsigned(second)) /10 when 5,
		       to_integer(unsigned(second)) rem 10 when 6,
				 0 when others;
		
	with num select
		DIG <= NUM0 when 0,
				 NUM1 when 1,
				 NUM2 when 2,
				 NUM3 when 3,
				 NUM4 when 4,
				 NUM5 when 5,
				 NUM6 when 6,
				 NUM7 when 7,
				 NUM8 when 8,
				 NUM9 when 9,
				 NUM_NULL when others;
				 
	with command select
		SEL <= SEL1 when 1,
				 SEL2 when 2,
				 SEL3 when 3,
				 SEL4 when 4,
				 SEL5 when 5,
				 SEL6 when 6,
				 SEL_NULL when others;
	
	process(rst_n,clk)
		variable count1: integer range 0 to 400000;
	begin
		if rst_n='0' then
			--SEL<="111110";
			--DIG<="11111111";
			command<=1;
			count1:=0;
		elsif clk'event and clk='1' then
			count1:=count1+1;
			if count1 >= 100000 then
				count1:=0;
				command<=command+1;
				if command = 10 then 
					command<=1;
				end if;
			end if;
		end if;
	end process;
end bev;

实验效果

在这里插入图片描述随便拍的一张照片,数码管显示的时间是00:10:12

注意事项

1、程序中用到了类型转换的操作,所以需要使用开头的库
2、这两段程序是从我的其他工程中摘出来的,没有测试,可能会有点小问题。如果有,改一下应该就可以了。
3、如果你不打算修改,这两个模块需要例化一下才能用。建一个顶层模块把他们之间的输入输出信号连起来。

如有不当之处欢迎指正

  • 2
    点赞
  • 0
    评论
  • 25
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:技术工厂 设计师:CSDN官方博客 返回首页

打赏作者

核聚变Q

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值