基于VHDL的数字钟设计

版权声明:本文为博主原创文章。 https://blog.csdn.net/u012763833/article/details/52902824

  这个是以前的一个作业,当时写的比较用心(感觉胸前的红领巾更鲜艳了)。先贴个程序有时间就再写写详细的设计思路吧!(哼,不信你还会继续写。。。)

工程结构如下:
这里写图片描述

下面分部贴上程序

1. 模块综合

-----------------------------------------------------
  -- 数字钟
----------------------------------------------------- 
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY CLOCK IS
PORT(                   CLK : IN STD_LOGIC;  -- 1Hz时钟信号输入
                C_SCALE_SEL : IN STD_LOGIC;  -- 时钟进制选择
                    C_RESET : IN STD_LOGIC;  -- 时钟复位信号
    C_SET_MIN, C_SET_HOUR : IN STD_LOGIC;  -- 时间调节
                   BUZZER : OUT STD_LOGIC;  -- 蜂鸣器控制
                SEGMENT_SEL : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);  -- 数码位选信号输出
                SEGMENT_SEG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 数码管短信信号输出
                  FLASH_LED : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));  -- 流水灯
END CLOCK;

ARCHITECTURE BHV OF CLOCK IS
   -- 调用秒钟计数模块声明
    COMPONENT SECOND_BCD_COUNT  
    PORT(clk_to_second, reset, set_min : IN STD_LOGIC;
                                  CO : OUT STD_LOGIC;
                                DATOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
    END COMPONENT;
    -- 调用分钟计数模块声明
    COMPONENT MINUTE_BCD_COUNT  
    PORT(clk_to_minute, reset, set_hour : IN STD_LOGIC;
                                     CO : OUT STD_LOGIC;
                                 DATOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
    END COMPONENT;
    -- 调用小时计数模块声明
    COMPONENT HOUR_BCD_COUNT  
    PORT(clk_to_hour, reset, SCALE_SEL : IN STD_LOGIC;
                                DATOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
    END COMPONENT;
    -- 调用译码显示模块声明
    COMPONENT SELTIME  
    PORT(            SCAN_CLK : IN STD_LOGIC;  -- 扫描时钟输入 
         HOUR, MINUTE, SECOND : IN STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 时间数据输入
                         SEL : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);  -- 位选信号输出                              
                         SEG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));  -- 段选信号输出
    END COMPONENT;
    -- 调用分频模块声明
    COMPONENT DEV  
    PORT(                  CLK_50MHz : IN STD_LOGIC;
         CLK_1Hz, CLK_5Hz, CLK_250Hz : OUT STD_LOGIC);
    END COMPONENT;
    -- 整点报时模块
    COMPONENT  ALERT  
    PORT(  CLK : IN STD_LOGIC;  -- 激励LED变化
          M_IN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 输入分钟显示数据 
          S_IN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 输入秒钟显示数据 
       SPEAKER : OUT STD_LOGIC;  -- 蜂鸣器控制
           LED : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));  -- 流水灯
    END COMPONENT;
    -- 按键延时消抖模块
    COMPONENT KEY_DELAY  
    PORT(CLK, KEY_IN : IN STD_LOGIC;  
             KEY_OUT : OUT STD_LOGIC);
    END COMPONENT;
SIGNAL AD_HOUR, AD_MIN : STD_LOGIC;  -- 时钟调节信号
SIGNAL S_CO, M_CO : STD_LOGIC;  -- 计数进位
SIGNAL C_CLK, SCAN_CLK, FLOW_CLK : STD_LOGIC;  -- 计数时钟,扫描时钟,流水灯驱动时钟
SIGNAL S_DAT, M_DAT, H_DAT : STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 秒,分,时显示数据
    BEGIN
        u1 : SECOND_BCD_COUNT PORT MAP(C_CLK, C_RESET, AD_MIN, S_CO, S_DAT);  -- 秒钟
        u2 : MINUTE_BCD_COUNT PORT MAP(S_CO, C_RESET, AD_HOUR, M_CO, M_DAT);  -- 分钟
        u3 : HOUR_BCD_COUNT   PORT MAP(M_CO, C_RESET, C_SCALE_SEL, H_DAT);  -- 小时
        u4 : SELTIME          PORT MAP(SCAN_CLK, H_DAT, M_DAT, S_DAT, SEGMENT_SEL, SEGMENT_SEG);  -- 译码显示
        u5 : DEV              PORT MAP(CLK, C_CLK, FLOW_CLK , SCAN_CLK);  -- 分频
        u6 : KEY_DELAY        PORT MAP(SCAN_CLK, C_SET_MIN, AD_MIN);  -- 分钟调整
        u7 : KEY_DELAY        PORT MAP(SCAN_CLK, C_SET_HOUR, AD_HOUR);  -- 小时调整
        u8 : ALERT            PORT MAP(FLOW_CLK, M_DAT,S_DAT, BUZZER, FLASH_LED);  -- 整点报时
END BHV;        

2. 时分秒计数模块

-----------------------------------------------------
 -- 小时24进制或12进制的BCD计数模块
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY HOUR_BCD_COUNT IS
PORT(clk_to_hour, reset, SCALE_SEL : IN STD_LOGIC;
                            DATOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END HOUR_BCD_COUNT;

ARCHITECTURE BHV OF HOUR_BCD_COUNT IS
SIGNAL COUNT_SHI, COUNT_GE : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN 
    PROCESS(clk_to_hour, reset)     BEGIN
        IF reset = '0'      THEN COUNT_SHI <= "0000"; COUNT_GE <= "0000"; -- 有复位信号,则清除计数。
        ELSIF clk_to_hour'EVENT AND clk_to_hour = '1'    THEN
           IF SCALE_SEL = '1' THEN  -- 24进制
                IF COUNT_SHI = "0010" AND COUNT_GE = "0011"     THEN COUNT_SHI <= "0000"; COUNT_GE <= "0000";  -- 24进制溢出清零
                ELSIF COUNT_GE < "1001"     THEN COUNT_GE <= COUNT_GE + 1;
                ELSE COUNT_GE <= "0000"; COUNT_SHI <= COUNT_SHI + 1;
                END IF;
            ELSE  -- 12进制
               IF COUNT_SHI = "0001" AND COUNT_GE = "0001"      THEN COUNT_SHI <= "0000"; COUNT_GE <= "0000";  -- 12进制溢出清零
              ELSIF COUNT_GE < "1001"       THEN COUNT_GE <= COUNT_GE + 1;
                ELSE COUNT_GE <= "0000"; COUNT_SHI <= COUNT_SHI + 1;
                END IF;
            END IF;
        END IF;
    DATOUT <= COUNT_SHI & COUNT_GE;  -- 数据输出
    END PROCESS;
END BHV;

-----------------------------------------------------
  -- 分钟BCD60进制计数
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY MINUTE_BCD_COUNT IS
PORT(clk_to_minute, reset, set_hour : IN STD_LOGIC;
                                 CO : OUT STD_LOGIC;
                             DATOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END MINUTE_BCD_COUNT;

ARCHITECTURE BHV OF MINUTE_BCD_COUNT IS
SIGNAL COUNT_SHI, COUNT_GE : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL COUNT_EN : STD_LOGIC;
BEGIN 
   CO <=  set_hour OR COUNT_EN;
    PROCESS(clk_to_minute, set_hour, reset)     BEGIN   
        IF reset = '0'      THEN COUNT_SHI <= "0000"; COUNT_GE <= "0000"; -- 有复位信号,则清除计数
        ELSIF clk_to_minute'EVENT AND clk_to_minute = '1'   THEN     
            IF COUNT_SHI = "0101" AND COUNT_GE  = "1001"   THEN 
                COUNT_SHI <= "0000"; COUNT_GE <= "0000";  COUNT_EN <= '1';  -- 计数进位(信号量不是立即赋值,需等下一个时钟信号到来。)
            ELSIF COUNT_GE < "1001"     THEN COUNT_GE <= COUNT_GE + 1; COUNT_EN <= '0'; 
            ELSE COUNT_GE <= "0000";  -- 计数溢出则清零,并产生进位
                IF COUNT_SHI < "1010"   THEN COUNT_SHI <= COUNT_SHI + 1;  
                ELSE COUNT_SHI <= "0000";  
                END IF;
            END IF;
        END IF;
    END PROCESS;
    DATOUT <= COUNT_SHI & COUNT_GE;  -- 数据输出
END BHV;

-----------------------------------------------------
  -- 秒钟BCD60进制计数
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY SECOND_BCD_COUNT IS
PORT(clk_to_second, reset, set_min : IN STD_LOGIC;
                                CO : OUT STD_LOGIC;
                            DATOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END SECOND_BCD_COUNT;

ARCHITECTURE BHV OF SECOND_BCD_COUNT IS
SIGNAL COUNT_SHI, COUNT_GE : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL COUNT_EN : STD_LOGIC;
BEGIN 
   CO <= set_min OR COUNT_EN;
    PROCESS(clk_to_second, reset, set_min)      BEGIN
   IF reset = '0'       THEN COUNT_SHI <= "0000"; COUNT_GE <= "0000"; -- 有复位信号,则清除计数
    ELSIF clk_to_second'EVENT AND clk_to_second = '1'   THEN     
        IF COUNT_SHI = "0101" AND COUNT_GE  = "1001"   THEN 
            COUNT_SHI <= "0000"; COUNT_GE <= "0000";  COUNT_EN <= '1';  -- 计数进位(信号量不是立即赋值,需等下一个时钟信号到来。)
        ELSIF COUNT_GE < "1001"     THEN COUNT_GE <= COUNT_GE + 1;  COUNT_EN <= '0';
        ELSE COUNT_GE <= "0000";  
            IF COUNT_SHI < "1010"   THEN COUNT_SHI <= COUNT_SHI + 1;  
            ELSE COUNT_SHI <= "0000";  
            END IF;
        END IF;
    END IF;
    DATOUT <= COUNT_SHI & COUNT_GE;  -- 数据输出
    END PROCESS;
END BHV;

3. 数码管译码显示模块

-----------------------------------------------------
  -- 数码管译码显示模块
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY SELTIME IS
PORT(            SCAN_CLK : IN STD_LOGIC;  -- 扫描时钟输入 
     HOUR, MINUTE, SECOND : IN STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 时间数据输入
                      SEL : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);  -- 位选信号输出
                      SEG : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));  -- 段选信号输出
END SELTIME;

ARCHITECTURE BHV OF SELTIME IS
SIGNAL SCAN_COUNT : STD_LOGIC_VECTOR(2 DOWNTO 0);  -- 扫描计数 
SIGNAL DAT : STD_LOGIC_VECTOR(3 DOWNTO 0);  
BEGIN   
   -- 位选扫描进程 
    SCAN : PROCESS(SCAN_CLK) BEGIN
        IF SCAN_CLK'EVENT AND SCAN_CLK = '1'   THEN 
            IF(SCAN_COUNT > "101")  THEN SCAN_COUNT <= "000";
            ELSE SCAN_COUNT <= SCAN_COUNT + 1;
            END IF;
        END IF;
        CASE SCAN_COUNT IS
            WHEN "000" => DAT <= SECOND(3 DOWNTO 0);
            WHEN "001" => DAT <= SECOND(7 DOWNTO 4);
            WHEN "010" => DAT <= MINUTE(3 DOWNTO 0);
            WHEN "011" => DAT <= MINUTE(7 DOWNTO 4);
            WHEN "100" => DAT <= HOUR(3 DOWNTO 0);
            WHEN "101" => DAT <= HOUR(7 DOWNTO 4);
            WHEN  OTHERS => NULL;
        END CASE;
    END PROCESS SCAN;
    -- 译码显示进程 共数码管编码
    DECODE :    PROCESS(SCAN_COUNT) BEGIN
        CASE DAT IS
            WHEN "0000" => SEG<="11000000"; 
            WHEN "0001" => SEG<="11111001"; 
            WHEN "0010" => SEG<="10100100"; 
            WHEN "0011" => SEG<="10110000"; 
            WHEN "0100" => SEG<="10011001"; 
            WHEN "0101" => SEG<="10010010"; 
            WHEN "0110" => SEG<="10000010"; 
            WHEN "0111" => SEG<="11111000"; 
            WHEN "1000" => SEG<="10000000"; 
            WHEN "1001" => SEG<="10010000"; 
            WHEN OTHERS => SEG<="11111111"; 
        END CASE;
    END PROCESS DECODE; 
    -- 3-8译码
    SEL <=  "111110" WHEN SCAN_COUNT = "000" ELSE 
              "111101" WHEN SCAN_COUNT = "001" ELSE 
              "111011" WHEN SCAN_COUNT = "010" ELSE 
              "110111" WHEN SCAN_COUNT = "011" ELSE 
              "101111" WHEN SCAN_COUNT = "100" ELSE 
              "011111" WHEN SCAN_COUNT = "101" ELSE 
              "111111";
END BHV;

4. 分配模块,晶振频率50MHz

-----------------------------------------------------
  -- 分频模块
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY DEV IS
PORT(                 CLK_50MHz : IN STD_LOGIC;
    CLK_1Hz, CLK_5Hz, CLK_250Hz : OUT STD_LOGIC);
END;

ARCHITECTURE BHV OF DEV IS
SIGNAL Q1 : INTEGER RANGE 0 TO 49999999;
SIGNAL Q2 : INTEGER RANGE 0 TO 199999;
SIGNAL Q3 : INTEGER RANGE 0 TO 9999999;
BEGIN
    PROCESS(CLK_50MHz) BEGIN
        IF CLK_50MHz'EVENT AND CLK_50MHz = '1' THEN
           -- 1Hz
            IF Q1 < 25000000        THEN CLK_1Hz <= '0'; Q1 <= Q1 + 1;
            ELSIF Q1 < 49999999     THEN CLK_1Hz <= '1'; Q1 <= Q1 + 1;
            ELSE Q1 <= 0;
            END IF;
            -- 250Hz
            IF Q2 < 100000      THEN CLK_250Hz <= '0'; Q2 <= Q2 + 1;
            ELSIF Q2 < 199999       THEN CLK_250Hz <= '1'; Q2 <= Q2 + 1; 
            ELSE Q2 <= 0;
            END IF;
            -- 5Hz
            IF Q3 < 5000000 THEN CLK_5Hz <= '0'; Q3 <= Q3 + 1;
            ELSIF Q3 < 9999999  THEN CLK_5Hz <= '1'; Q3 <= Q3 + 1; 
            ELSE Q3 <= 0;
            END IF;
        END IF;
    END PROCESS;
END;

5. 按键延时消抖模块(PS:这个很重要,网上借鉴的。。。~_~)

-----------------------------------------------------
  -- 按键延时消抖模块
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY KEY_DELAY IS
PORT(CLK, KEY_IN : IN STD_LOGIC;  
         KEY_OUT : OUT STD_LOGIC);
END KEY_DELAY;

ARCHITECTURE BHV OF KEY_DELAY IS
BEGIN
PROCESS(CLK, KEY_IN) 
VARIABLE COUNT : INTEGER RANGE 0 TO 10;
BEGIN
    IF CLK'EVENT AND CLK = '1' THEN
        IF KEY_IN = '0' THEN
            IF COUNT < 10    THEN COUNT := COUNT + 1;
            ELSE COUNT := COUNT;  -- 赋予变量的值是即刻生效的,在此后的代码中,此变量将使用新的变量值。
            END IF;
            IF COUNT = 9    THEN KEY_OUT <= '1';    
            ELSE KEY_OUT <= '0';    
            END IF;
        ELSE COUNT := 0;    
        END IF;
    END IF;
END PROCESS;
END BHV;

6. 报时模块

-----------------------------------------------------
  -- 报时模块,就是整点时发生点变化喽,这个你随意。Hi,guys.
-----------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY ALERT IS
PORT(  CLK : IN STD_LOGIC;  -- 激励LED变化
      M_IN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 输入分钟显示数据 
      S_IN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);  -- 输入秒钟显示数据 
   SPEAKER : OUT STD_LOGIC;  -- 蜂鸣器控制
       LED : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));  -- 流水灯
END ALERT;

ARCHITECTURE BHV OF ALERT IS
SIGNAL SEL : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL COUNT : STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN  
    REG : PROCESS(CLK) BEGIN
        IF CLK'EVENT AND CLK = '1'      THEN 
            IF COUNT < "111"    THEN COUNT <= COUNT + 1;
            ELSE COUNT <= "000"; 
            END IF;
        END IF;
    END PROCESS REG;
    FLOW : PROCESS(COUNT, M_IN, S_IN) BEGIN
        IF M_IN = "00000000"    AND S_IN < "00001001"   THEN  -- 整点闪烁
            CASE COUNT IS
                WHEN "000" => LED <="1000";  
                WHEN "001" => LED <="0100";  
                WHEN "010" => LED <="0010";  
                WHEN "011" => LED <="0001";
                WHEN "111" => LED <="1111"; 
                WHEN "101" => LED <="0000";
                WHEN "110" => LED <="1111";
                WHEN OTHERS => LED <="0000";
            END CASE;
        ELSE    LED <= "0000";
        END IF;
    END PROCESS FLOW;
    BEEP : PROCESS( M_IN, S_IN) BEGIN
        IF M_IN = "00000000"    AND S_IN < "0000010"    THEN  -- 整点报时
          SPEAKER <= '0';
        ELSE SPEAKER <= '1';
        END IF;
    END PROCESS BEEP;
END BHV;    

猜你喜欢

转载自blog.csdn.net/u012763833/article/details/52902824
今日推荐