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

举报
莫言2021 发表于 2021/11/05 10:07:23 2021/11/05
【摘要】 简介:本文主要介绍如何用VHDL设计一个时钟(可以产生时分秒的信号),然后用数码管显示出时分秒。实验器材: FPGA开发板、板载6位数码管(共阳极设计思路设计两个模块,一个模块负责产生时分秒的信号,另一个模块负责驱动数码管显示出时分秒的时间。然后在顶层模块中把两个模块的输入输出进行例化。(本文只给出底层模块的VHDL程序,顶层模块进行例化就可以了)原理介绍时钟:通过计数FPGA开发板自带的4...

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

如有不当之处欢迎指正
————————————————
版权声明:本文为CSDN博主「核聚变Q」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/JACK__Q/article/details/113183633

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。