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、如果你不打算修改,这两个模块需要例化一下才能用。建一个顶层模块把他们之间的输入输出信号连起来。

如有不当之处欢迎指正

  • 6
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个设计8位可逆计数器并使用数码管显示VHDL代码: ```vhdl entity reversible_counter_display is port ( clk : in std_logic; rst : in std_logic; seg : out std_logic_vector(7 downto 0) ); end entity reversible_counter_display; architecture rtl of reversible_counter_display is signal counter : std_logic_vector(7 downto 0) := (others => '0'); signal count : integer range 0 to 99 := 0; begin process(clk, rst) begin if rst = '1' then counter <= (others => '0'); count <= 0; elsif rising_edge(clk) then if count = 99 then count <= 0; counter <= (others => '0'); else count <= count + 1; counter <= std_logic_vector(to_unsigned(count, 8)); end if; end if; end process; seg <= to_7seg(counter); end architecture rtl; -- 数码管显示模块 library ieee; use ieee.std_logic_1164.all; entity to_7seg is port ( num : in std_logic_vector(7 downto 0); seg : out std_logic_vector(7 downto 0) ); end entity to_7seg; architecture rtl of to_7seg is begin with num select seg <= "0000001" when "00000000", -- 0 "1001111" when "00000001", -- 1 "0010010" when "00000010", -- 2 "0000110" when "00000011", -- 3 "1001100" when "00000100", -- 4 "0100100" when "00000101", -- 5 "0100000" when "00000110", -- 6 "0001111" when "00000111", -- 7 "0000000" when "00001000", -- 8 "0001100" when "00001001", -- 9 "0010000" when "00001010", -- A "0001000" when "00001011", -- b "0000010" when "00001100", -- C "1000110" when "00001101", -- d "0100001" when "00001110", -- E "0100011" when "00001111", -- F "1111111" when others; -- Off end architecture rtl; ``` 在这个代码中,我们使用了一个8位的计数器,使用可逆计数算法实现。当计数器的值达到99时,它将重新开始计数,而不是继续增加到100。这个算法允许计数器在任何时候都能回到0,因此它是可逆的。 我们还使用了一个 `to_7seg` 模块来将计数器的值转换为七段显示格式。这个模块使用一个 `with select` 语句,将数字转换为相应的七段显示码。它还包括一个 "Off" 选项,用于在计数器值超出范围时关闭数码管显示。 为了测试这个设计,你可以使用一个测试台来提供时钟和复位信号,并监视数码管显示的输出。以下是一个简单的测试台: ```vhdl entity tb_reversible_counter_display is end entity tb_reversible_counter_display; architecture testbench of tb_reversible_counter_display is signal clk : std_logic := '0'; signal rst : std_logic := '0'; signal seg : std_logic_vector(7 downto 0); begin dut : entity work.reversible_counter_display port map ( clk => clk, rst => rst, seg => seg ); process begin clk <= '0'; wait for 10 ns; clk <= '1'; wait for 10 ns; end process; process begin rst <= '1'; wait for 5 ns; rst <= '0'; wait for 5 ns; rst <= '1'; wait; end process; process begin wait for 100 ns; assert seg = "00000001" report "Error: Expected '0' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00000010" report "Error: Expected '1' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00000011" report "Error: Expected '2' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00000100" report "Error: Expected '3' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00000101" report "Error: Expected '4' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00000110" report "Error: Expected '5' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00000111" report "Error: Expected '6' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00001000" report "Error: Expected '7' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00001001" report "Error: Expected '8' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00001010" report "Error: Expected '9' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "00001100" report "Error: Expected 'C' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "1000110" report "Error: Expected 'd' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "0100001" report "Error: Expected 'E' but got '" & std_logic'image(seg) & "'" severity error; wait for 100 ns; assert seg = "0100011" report "Error: Expected 'F' but got '" & std_logic'image(seg) & "'" severity error; wait; end process; end architecture testbench; ``` 这个测试台使用了一个 `assert` 语句,来检查数码管显示的输出是否正确。你可以将这个代码与可逆计数器和数码管显示的代码一起编译,并运行一个仿真,以测试设计的行为。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值