打印

[转] vhdl数字钟的设计

[复制链接]
733|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lefeng|  楼主 | 2018-9-28 22:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、系统的设计要求
假设外部输入脉冲为1Hz,要求使用该频率设计一个时间可调,并通过LED七段共阴极数码管能够显示时、分、秒的数字钟。
二、系统的设计实现
众所周知,一天等于24h,1h等于60min,1min等于60s。进行设计数字钟的设计时,先对1s的时钟进行计数,当计数达到60次时,输出1个分钟(min)脉冲;当1min的时钟计数达到60次时,输出1个小时(h)脉冲,若1h时钟计数达到23次时,并且1min的计数到59次、1s的计数也达到59次,再来1个1s的脉冲,数字钟就自己复位,重新从零开始计时。
综上所述,数字钟由3个计数模块(二十四进制计数器、十进制计数器和六进制计数器)、7段LED驱动显示模块和顶层模块构成,如图下所示。顶层模块通过调用相应的模块,将这些模块进行有机的连接即可实现设计任务。
1.顶层模块程序
顶层模块程序的实体中应定义时钟脉冲输入端(CLK)、设置时间使能端(SET)。时间调整输入端(包括时、分、秒的高位和低位)、时钟数据显示输出端(包括时、分、秒的高位和低位)。
由于十进制计数模块和六进制计数模块会产生计数溢出信号(CARRY_OUT)而这些溢出信号有可能作为下一计数模块的时钟输入脉冲(CLK),因此在顶层模块程序的结构体中需要定义相应的暂存计数溢出信号(CARRY1~CARRY4)。3个计数模块的输出将为4位,这些4位输出的数据作为LED驱动模块的显示内容,所以也需定义一些4为输出信号。顶层模块程序编写如下:
--数字钟的顶层模块程序 dianzizhong.VHD
  LIBRARY  IEEE;
  USE  IEEE.STD_LOGIC_1164.ALL;
  ENTITY  dianzizhong   IS
PORT( CLK: IN  STD_LOGIC;                          --定义外部脉冲输入端
      SET: IN  STD_LOGIC;                          --设置时间使能端
      DIN_S_L: IN STD_LOGIC_VECTOR(3 DOWNTO 0);     --秒钟的低位调整输入端
      DIN_S_H: IN STD_LOGIC_VECTOR(3 DOWNTO 0);     --秒钟的高位调整输入端
      DIN_M_L: IN STD_LOGIC_VECTOR(3 DOWNTO 0);     --分钟的低位调整输入端
      DIN_M_H: IN STD_LOGIC_VECTOR(3 DOWNTO 0);    --分钟的高位调整输入端
      DIN_H_L: IN STD_LOGIC_VECTOR(3 DOWNTO 0);     --小时的低位调整输入端
      DIN_H_H: IN STD_LOGIC_VECTOR(3 DOWNTO 0);     --小时的高位调整输入端
      CQ_S_L: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);    --秒钟的低位显示输入端
      CQ_S_H: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);    --秒钟的高位显示输入端
      CQ_M_L: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);    --分钟的低位显示输入端
      CQ_M_H: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);    --分钟的高位显示输入端
      CQ_H_L: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);    --小时的低位显示输入端
      CQ_H_H: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));   --小时的高位显示输入端
  END dianzizhong;
  ARCHITECTURE ART OF dianzizhong IS
  COMPONENT CNT10
PORT(CLK: IN STD_LOGIC;                            --定义外部脉冲输入端
      SET: IN STD_LOGIC;                            --设置时间使能端
      DIN: IN STD_LOGIC_VECTOR(3 DOWNTO 0);      --预置时间值输入端
      CQ: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);     --十进制计数输出端
      CARRY_OUT: OUT STD_LOGIC);                 --十进制计数溢出端
  END COMPONENT CNT10;
  COMPONENT CNT6
PORT(CLK: IN STD_LOGIC;                           --定义外部脉冲输入端
      SET:IN STD_LOGIC;                            --设置时间使能端
      DIN: IN STD_LOGIC_VECTOR(3 DOWNTO 0);     --预置时间值输入端
      CQ: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);      --六进制计数输入端
      CARRY_OUT: OUT STD_LOGIC);                 --六进制计数溢出端
  END COMPONENT CNT6;
  COMPONENT CNT24
PORT(CLK: IN STD_LOGIC;                            --定义外部脉冲输入端
      SET:IN STD_LOGIC;                             --设置时间使能端
      DIN_H: IN STD_LOGIC_VECTOR(3 DOWNTO 0);    --预置时间的高位输入端
      DIN_L: IN STD_LOGIC_VECTOR(3 DOWNTO 0);    --预置时间的低位输入端
      CQ_H: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);   --计数高位输出端
      CQ_L: OUT STD_LOGIC_VECTOR(3 DOWNTO 0));   --计数低位输出端
  END COMPONENT CNT24;
COMPONENT LED_DRIV IS
   PORT( DIN: IN STD_LOGIC_VECTOR(3 DOWNTO 0);        --显示数据输入端
     DOUT: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));    --显示数据输出端
END COMPONENT LED_DRIV;
  SIGNAL CARRY1: STD_LOGIC;
  SIGNAL CARRY2: STD_LOGIC;
  SIGNAL CARRY3: STD_LOGIC;
  SIGNAL CARRY4: STD_LOGIC;
  SIGNAL CQI_S_L: STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL CQI_S_H: STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL CQI_M_L: STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL CQI_M_H: STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL CQI_H_L: STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL CQI_H_H: STD_LOGIC_VECTOR(3 DOWNTO 0);
  BEGIN                     --使用元件例化语句,通过基本模块的级联实现数字钟
  U0: CNT10 PORT MAP(CLK=>CLK,SET=>SET,DIN=>DIN_S_L,
            CQ=>CQI_S_L,CARRY_OUT=>CARRY1);
  U2: CNT6 PORT MAP(CLK=>CARRY1,SET=>SET,DIN=>DIN_S_H,
            CQ=>CQI_S_H,CARRY_OUT=>CARRY2);
  U3: CNT10 PORT MAP(CLK=>CARRY2,SET=>SET,DIN=>DIN_M_L,
            CQ=>CQI_M_L,CARRY_OUT=>CARRY3);
  U4: CNT6 PORT MAP(CLK=>CARRY3,SET=>SET,DIN=>DIN_M_H,
            CQ=>CQI_M_H,CARRY_OUT=>CARRY4);
  U5: CNT24 PORT MAP(CLK=>CARRY4,SET=>SET,DIN_H=>DIN_H_H,
            DIN_L=>DIN_H_L,CQ_H=>CQI_H_H,CQ_L=>CQI_H_L);
  U6: LED_DRIV PORT MAP(DIN=>CQI_S_L,DOUT=>CQ_S_L);
  U7: LED_DRIV PORT MAP(DIN=>CQI_S_H,DOUT=>CQ_S_H);
  U8: LED_DRIV PORT MAP(DIN=>CQI_M_L,DOUT=>CQ_M_L);
  U9: LED_DRIV PORT MAP(DIN=>CQI_M_H,DOUT=>CQ_S_H);
  U10: LED_DRIV PORT MAP(DIN=>CQI_H_L,DOUT=>CQ_H_L);
  U11: LED_DRIV PORT MAP(DIN=>CQI_H_H,DOUT=>CQ_H_H);
  END ART;
2.十进制计数器模块程序
使用VHDL编写程序时,在实体中应定义时钟脉冲输入端(CLK)、设置时间使能端(SET)、预置数据输入端(DIN)、计数脉冲输出端(CQ)和计数脉冲溢出端(CARRY_OUT)。十进制计数器模块程序编写如下:
--十进制计数器的源程序CNT10.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNT10  IS
  PORT( CLK: IN  STD_LOGIC;
        SET: IN  STD_LOGIC;
        DIN: IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
         CQ: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
        CARRY_OUT: OUT STD_LOGIC);
END CNT10;
ARCHITECTURE ART OF CNT10 IS
SIGNAL CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
  PROCESS(CLK,SET,DIN)
    BEGIN
      IF SET='1' THEN
               CQI<=DIN;
               CARRY_OUT<='0';
        ELSIF CLK'EVENT AND CLK='1' THEN
            IF CQI="1001"  THEN
              CQI<="0000";
              CARRY_OUT<='1';
              ELSE
                CQI<=CQI+'1';
                CARRY_OUT<='0';
             END IF;
           END IF;
      END PROCESS ;
      CQ<=CQI;
END ART;
3.六进制计数器模块程序
使用VHDL编写程序时,在实体中应定义时钟脉冲输入端(CLK)、设置时间使能端(SET)、预置数据输入端(DIN)、计数脉冲输出端(CQ)和计数脉冲溢出端(CARRY_OUT)。六进制计数器模块程序编写如下:
--六进制计数器的源程序CNT6.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY  CNT6  IS
  PORT( CLK: IN  STD_LOGIC;
        SET: IN  STD_LOGIC;
        DIN: IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
         CQ: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
        CARRY_OUT: OUT STD_LOGIC);
END CNT6;
ARCHITECTURE ART OF CNT6 IS
SIGNAL CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
  PROCESS(CLK,SET,DIN)
    BEGIN
      IF SET='1' THEN
               CQI<=DIN;
               CARRY_OUT<='0';
        ELSIF CLK'EVENT AND CLK='1' THEN
            IF CQI="0101"  THEN
              CQI<="0000";
              CARRY_OUT<='1';
              ELSE
                CQI<=CQI+'1';
                CARRY_OUT<='0';
             END IF;
           END IF;
      END PROCESS ;
      CQ<=CQI;
END ART;
4.二十四进制计数器模块程序
使用VHDL编写程序时,在实体中应定义时钟脉冲输入端(CLK)、设置时间使能端(SET_)、预置数据输入端(DIN_H、DIN_L)、计数脉冲输出端(CQ_H、CQ_L)。二十四进制计数器模块程序编写如下:
   
--二十四进制计数器的源程序CNT24.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY  CNT24  IS
  PORT( CLK: IN  STD_LOGIC;
        SET: IN  STD_LOGIC;
        DIN_H: IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
        DIN_L: IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
         CQ_H: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
         CQ_L: OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END CNT24;
ARCHITECTURE ART OF CNT24 IS
SIGNAL CQI_H:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL CQI_L:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
  PROCESS(CLK,SET,DIN_H,DIN_L)
    BEGIN
      IF SET='1' THEN
               CQI_H<=DIN_H;
               CQI_L<=DIN_L;
        ELSIF CLK'EVENT AND CLK='1' THEN
            IF (CQI_H="0010" AND CQI_L="0011")  THEN
              CQI_H<="0000";
              CQI_L<="0000";
            ELSIF (CQI_H/="0010" AND CQI_L="1001") THEN
              CQI_H<=CQI_H+'1';
              CQI_L<="0000";
            ELSE
              CQI_H<=CQI_H;
              CQI_L<=CQI_L+1;
             END IF;
          END IF;
       END PROCESS ;
        CQ_H<=CQI_H;
        CQ_L<=CQI_L;
END ART;
5. 7段LED显示驱动模块程序

7段LED由7个发光二极管组成,当某一发光二极管导通时,相应地点亮某一点或某一段笔画,通过二极管不同的亮暗组合形成不同的数字、字母及其它符号。其结构如下               
--共阴极LED显示模块程序LED_DRIV.VHD  
LIBRARY  IEEE;
USE  IEEE.STD_LOGIC_1164.ALL;

ENTITY LED_DRIV IS
   PORT (DIN: IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
         DOUT: OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END LED_DRIV;

ARCHITECTURE ART OF LED_DRIV IS
   BEGIN
     PROCESS(DIN)
       BEGIN
         CASE DIN IS
           WHEN "0000"=>DOUT<="0111111";    --显示“0”
           WHEN "0001"=>DOUT<="0000110";    --显示“1”
           WHEN "0010"=>DOUT<="1011011";    --显示“2”
           WHEN "0011"=>DOUT<="1001111";    --显示“3”
           WHEN "0100"=>DOUT<="1100110";    --显示“4”
           WHEN "0101"=>DOUT<="1101101";    --显示“5”
           WHEN "0110"=>DOUT<="1111101";    --显示“6”
           WHEN "0111"=>DOUT<="0000111";    --显示“7”
           WHEN "1000"=>DOUT<="1111111";    --显示“8”
           WHEN "1001"=>DOUT<="1101111";    --显示“9”
           WHEN OTHERS=>NULL;
         END CASE;
     END PROCESS;
END ART;

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

200

主题

1087

帖子

0

粉丝