赞
踩
一、设计任务与要求
设计一个数字时钟系统,该系统应包含准确的计时、直观的显示、方便的校时和复位功能。采用EDA自顶向下的设计方法,在Quartus II环境中,结合原理图和VHDL文本混合输入,完成数字时钟系统的整体设计、各功能模块的程序编写、仿真验证,并在FPGA实验开发板上实现。系统需实现时、分、秒的计时,通过6个LED七段数码管显示时间,支持通过按键进行小时和分钟的单独调整,以及通过按键进行系统复位。
二、数字钟系统设计分析
在数字钟系统设计中,我们采用了自顶向下的方法,将系统划分为多个子模块以实现所需功能。主要模块设计概述如下:
1、分频器模块:用于降低时钟频率,生成1Hz的时钟信号和1KHz的刷新信号,分别用于时间计量和数码管刷新。
2、信号分配模块:负责将1Hz时钟信号和复位信号分发至秒、分、时计时器,确保同步计时和复位。
3、计时器模块:采用24进制和60进制计数器分别记录小时、分钟和秒数,通过进位信号实现连续计时。
4、数据选择器与消抖模块:选择时间调整模式,并使用D触发器型电路消除按键抖动,确保输入信号的稳定性。
5、数码管译码器模块:将计时器的二进制输出转换为数码管可显示的编码,并行输出到显示模块。
6、显示与提醒模块:通过1KHz刷新信号驱动数码管动态显示时间,同时实现闹钟提醒功能,当时间达到预设值时触发蜂鸣器。
7、模块整合:通过原理图设计连接各模块,优化信号传输路径,形成完整的数字钟系统。
三、管脚配置及程序下载硬件验证
1、管脚配置
在FPGA设计流程中,管脚配置是确保设计正确映射到物理硬件的关键步骤。针对选用的FPGA开发板型号(EP4CE10F17C8),进行了精确的管脚分配。
(1)了解开发板资源:查阅FPGA开发板的用户手册文档,详细了解了开发板上的各种资源。根据数字钟系统的设计需求,我们规划了所需使用的IO引脚,包括用于连接数码管显示的时间显示引脚、用于接收按键输入的引脚等。
(2)Quartus II环境下的管脚分配:在明确资源规划后,打开了Quartus II软件,在项目中进行了管脚配置。通过软件提供的图形化界面,逐一将VHDL代码中定义的信号与实际硬件的引脚进行对应。
2、程序下载硬件验证
在完成管脚配置后,将VHDL代码编译生成的二进制文件(如“MARQUEE.sof”)通过FPGA开发板的下载工具(如USB-Blaster)下载到FPGA开发板中,进行硬件验证。
(1)时间显示验证:在正常运行状态下,观察数字钟是否能够准确无误地显示当前的时间,包括小时、分钟和秒数。通过长时间运行和多次观察,验证了时间显示的准确性,确保每个时间单位的更新都是准确无误的。
(2)复位功能验证:按下“复位”键,数字钟迅速且完全地重置为初始状态。这时所有时间单位(小时、分钟、秒)都归零。当松开“复位”键时,系统从初始时间开始计时。
(3)闹钟功能验证:在闹钟功能验证环节,设定了特定的时间(如“00:00:00”和“12:00:00”)作为触发蜂鸣器响起的条件。当达到这些特定时间时,观察到蜂鸣器按预期响起2秒,从而验证了闹钟功能的实现。
(4)时间调分功能验证:按下“调分”键。当按下“调分”键时,数字钟的分钟显示将按照预设的1Hz速度递增。当松开“调分”键,时间又按照正常时间开始进行计时。
(5)时间调时功能验证:按下“调时”键。当按下“调时”键时,数字钟的小时显示将按照预设的1Hz速度递增。当松开“调时”键,时间又按照正常时间开始进行计时。
三、代码与原理图连接
1、CLOCKDIVIDER:
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
-
- ENTITY CLOCKDIVIDER IS
- PORT (
- CLK_IN : IN STD_LOGIC;
- CLK_1KHZ : OUT STD_LOGIC;
- CLK_1HZ : OUT STD_LOGIC
- );
- END CLOCKDIVIDER;
-
- ARCHITECTURE BEHAVIORAL OF CLOCKDIVIDER IS
- SIGNAL COUNT_1KHZ : INTEGER RANGE 0 TO 24999 := 0;
- SIGNAL COUNT_1HZ : INTEGER RANGE 0 TO 24999999 := 0;
- SIGNAL TEMP_1KHZ : STD_LOGIC := '0';
- SIGNAL TEMP_1HZ : STD_LOGIC := '0';
- BEGIN
- PROCESS(CLK_IN)
- BEGIN
- IF CLK_IN = '1' AND CLK_IN'EVENT THEN
- IF COUNT_1KHZ = 24999 THEN
- COUNT_1KHZ <= 0;
- TEMP_1KHZ <= NOT TEMP_1KHZ;
- ELSE
- COUNT_1KHZ <= COUNT_1KHZ + 1;
- END IF;
- END IF;
- END PROCESS;
-
- CLK_1KHZ <= TEMP_1KHZ;
-
- PROCESS(CLK_IN)
- BEGIN
- IF CLK_IN = '1' AND CLK_IN'EVENT THEN
- IF COUNT_1HZ = 24999999 THEN
- COUNT_1HZ <= 0;
- TEMP_1HZ <= NOT TEMP_1HZ;
- ELSE
- COUNT_1HZ <= COUNT_1HZ + 1;
- END IF;
- END IF;
- END PROCESS;
-
- CLK_1HZ <= TEMP_1HZ;
-
- END BEHAVIORAL;
2、MUX_TWO_ONE:
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-
- ENTITY MUX_TWO_ONE IS
- PORT(
- KEY : IN STD_LOGIC; -- 选择信号
- CLK_1HZ : IN STD_LOGIC; -- 1HZ时钟输入
- CLK_QOUT : IN STD_LOGIC; -- 时钟输入
- CLK_OUT : OUT STD_LOGIC -- 输出时钟
- );
- END MUX_TWO_ONE;
-
- ARCHITECTURE MUX OF MUX_TWO_ONE IS
- SIGNAL D1 : STD_LOGIC:='1';
- SIGNAL D2 : STD_LOGIC:='1';
- SIGNAL D3 : STD_LOGIC:='1';
- SIGNAL OUT_KEY : STD_LOGIC;
- BEGIN
- P1: PROCESS(CLK_1HZ)
- BEGIN
- IF CLK_1HZ'EVENT AND CLK_1HZ = '1' THEN
- D1<=KEY;
- D2<=D1;
- D3<=D2;
- END IF;
- OUT_KEY<=D1 OR D2 OR D3;
- END PROCESS P1;
- P2:PROCESS(OUT_KEY)
- BEGIN
- IF OUT_KEY = '0' THEN
- CLK_OUT <= CLK_1HZ;
- ELSE
- CLK_OUT <= CLK_QOUT;
- END IF;
- END PROCESS P2;
- END MUX;
3、SPLITTER_ONE_THREE:
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-
- ENTITY SPLITTER_ONE_THREE IS
- PORT(
- INPUT : IN STD_LOGIC; -- 输入
- OUTPUTONE : OUT STD_LOGIC; -- 输出1
- OUTPUTTWO : OUT STD_LOGIC; -- 输出2
- OUTPUTTHREE : OUT STD_LOGIC -- 输出3
- );
- END SPLITTER_ONE_THREE;
-
- ARCHITECTURE SPLITTER OF SPLITTER_ONE_THREE IS
- BEGIN
- PROCESS(INPUT)
- BEGIN
- IF INPUT='1' THEN
- OUTPUTONE<='1';
- OUTPUTTWO<='1';
- OUTPUTTHREE<='1';
- ELSE
- OUTPUTONE<='0';
- OUTPUTTWO<='0';
- OUTPUTTHREE<='0';
- END IF;
- END PROCESS;
- END SPLITTER;
4、clock_display_24:
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
-
- entity clock_display_24 is
- Port (
- seconds : in std_logic_vector(4 downto 0); -- 输入的秒数(0-59)
- seg_ten : out std_logic_vector(6 downto 0); -- 十位数码管段
- seg_one : out std_logic_vector(6 downto 0)); -- 个位数码管段
- end clock_display_24;
- architecture Behavioral of clock_display_24 is
- -- 七段数码管译码函数
- function seven_seg_decode(num : integer range 0 to 9) return std_logic_vector is
- variable seg : std_logic_vector(6 downto 0);
- begin
- case num is
- when 0 => seg := "1000000"; -- A到G(DP省略)
- when 1 => seg := "1111001";
- when 2 => seg := "0100100";
- when 3 => seg := "0110000";
- when 4 => seg := "0011001";
- when 5 => seg := "0010010";
- when 6 => seg := "0000010";
- when 7 => seg := "1111000";
- when 8 => seg := "0000000";
- when 9 => seg := "0010000";
- when others => seg := "1111111"; -- 错误指示
- end case;
- return seg;
- end function;
-
- -- 声明变量来存储十位和个位的值
- signal ten_val, one_val : integer range 0 to 9;
-
- begin
- process(seconds)
- begin
- -- 计算十位
- ten_val <= to_integer(unsigned(seconds)) / 10;
- -- 调用译码函数并更新输出
- seg_ten <= seven_seg_decode(ten_val);
- end process;
- process(seconds)
- begin
- -- 计算个位
- one_val <= to_integer(unsigned(seconds)) mod 10;
-
- -- 调用译码函数并更新输出
- seg_one <= seven_seg_decode(one_val);
- end process;
- end Behavioral;
5、CLOCK_24:
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-
- ENTITY CLOCK_24 IS
- PORT(
- CLK : IN STD_LOGIC; -- 时钟输入
- RST : IN STD_LOGIC; -- 重置输入
- CLK_M : OUT STD_LOGIC_VECTOR(4 DOWNTO 0) -- 当前时间
- );
- END CLOCK_24;
-
- ARCHITECTURE CLOCK2 OF CLOCK_24 IS
- SIGNAL TEM_CLK_M : STD_LOGIC_VECTOR(4 DOWNTO 0) := (OTHERS => '0');
- BEGIN
- PROCESS(CLK, RST)
- BEGIN
- IF RST = '0' THEN
- TEM_CLK_M <= (OTHERS => '0');
- ELSIF CLK'EVENT AND CLK = '1' THEN
- IF TEM_CLK_M = "11000" THEN
- TEM_CLK_M <= (OTHERS => '0');
- ELSE
- TEM_CLK_M <= TEM_CLK_M + 1;
- END IF;
- END IF;
- END PROCESS;
- CLK_M <= TEM_CLK_M;
- END CLOCK2;
6、CLOCK_60:
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-
- ENTITY CLOCK_60 IS
- PORT(
- CLK : IN STD_LOGIC; -- 时钟输入
- RST : IN STD_LOGIC; -- 重置输入
- QOUT : OUT STD_LOGIC; -- 进位输出信号
- CLK_M : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) -- 当前时间
- );
- END CLOCK_60;
-
- ARCHITECTURE CLOCK1 OF CLOCK_60 IS
- SIGNAL TEM_CLK_M : STD_LOGIC_VECTOR(5 DOWNTO 0) := (OTHERS => '0');
- BEGIN
- PROCESS(CLK, RST)
- BEGIN
- IF RST = '0' THEN
- TEM_CLK_M <= (OTHERS => '0');
- QOUT <= '0';
- ELSIF CLK'EVENT AND CLK = '1' THEN
- IF TEM_CLK_M = "111011" THEN
- QOUT <= '1';
- TEM_CLK_M <= (OTHERS => '0');
- ELSE
- TEM_CLK_M <= TEM_CLK_M + 1;
- QOUT <= '0';
- END IF;
- END IF;
- END PROCESS;
- CLK_M <= TEM_CLK_M;
- END CLOCK1;
7、clock_display :
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
-
- entity clock_display is
- Port (
- seconds : in std_logic_vector(5 downto 0); -- 输入的秒数(0-59)
- seg_ten : out std_logic_vector(6 downto 0); -- 十位数码管段
- seg_one : out std_logic_vector(6 downto 0)); -- 个位数码管段
-
- end clock_display;
- architecture Behavioral of clock_display is
- -- 七段数码管译码函数
- function seven_seg_decode(num : integer range 0 to 9) return std_logic_vector is
- variable seg : std_logic_vector(6 downto 0);
- begin
- case num is
- when 0 => seg := "1000000"; -- A到G(DP省略)
- when 1 => seg := "1111001";
- when 2 => seg := "0100100";
- when 3 => seg := "0110000";
- when 4 => seg := "0011001";
- when 5 => seg := "0010010";
- when 6 => seg := "0000010";
- when 7 => seg := "1111000";
- when 8 => seg := "0000000";
- when 9 => seg := "0010000";
- when others => seg := "1111111"; -- 错误指示
- end case;
- return seg;
- end function;
-
- -- 声明变量来存储十位和个位的值
- signal ten_val, one_val : integer range 0 to 9;
-
- begin
- process(seconds)
- begin
- -- 计算十位
- ten_val <= to_integer(unsigned(seconds)) / 10;
- -- 调用译码函数并更新输出
- seg_ten <= seven_seg_decode(ten_val);
- end process;
- process(seconds)
- begin
- -- 计算个位
- one_val <= to_integer(unsigned(seconds)) mod 10;
-
- -- 调用译码函数并更新输出
- seg_one <= seven_seg_decode(one_val);
- end process;
- end Behavioral;
8、TUBE:
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-
- ENTITY TUBE IS
- PORT (
- CLK : IN STD_LOGIC;
- TUBE_SIX : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
- TUBE_FIVE : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
- TUBE_FOUR : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
- TUBE_THREE : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
- TUBE_TWO : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
- TUBE_ONE : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
- TUBE_NOW : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
- TIME_CLOCK : OUT STD_LOGIC;
- EN : OUT STD_LOGIC_VECTOR(5 DOWNTO 0)
- );
- END TUBE;
-
- ARCHITECTURE ONE OF TUBE IS
- SIGNAL TEM_EN : STD_LOGIC_VECTOR(5 DOWNTO 0) := "011111";
- SIGNAL TEM_TIME_CLOCK : STD_LOGIC := '1';
- SIGNAL FLAG : STD_LOGIC := '0';
- SIGNAL TEM_TUBE_SIX : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0000000";
- SIGNAL TEM_TUBE_FIVE : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0000000";
- SIGNAL TEM_TUBE_FOUR : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0000000";
- SIGNAL TEM_TUBE_THREE : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0000000";
- SIGNAL TEM_TUBE_TWO : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0000000";
- SIGNAL TEM_TUBE_ONE : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0000000";
- BEGIN
- P1: PROCESS(CLK)
- BEGIN
- IF CLK'EVENT AND CLK = '1' THEN
- TEM_EN <= TEM_EN(4 DOWNTO 0) & TEM_EN(5);
- EN <= TEM_EN;
- END IF;
- END PROCESS P1;
-
- P2: PROCESS(TEM_EN, TUBE_ONE, TUBE_TWO, TUBE_THREE, TUBE_FOUR, TUBE_FIVE, TUBE_SIX)
- BEGIN
- CASE TEM_EN IS
- WHEN "111101" => TUBE_NOW <= TUBE_ONE;
- WHEN "111011" => TUBE_NOW <= TUBE_TWO;
- WHEN "110111" => TUBE_NOW <= TUBE_THREE;
- WHEN "101111" => TUBE_NOW <= TUBE_FOUR;
- WHEN "011111" => TUBE_NOW <= TUBE_FIVE;
- WHEN "111110" => TUBE_NOW <= TUBE_SIX;
- WHEN OTHERS => TUBE_NOW <= (OTHERS => '0');
- END CASE;
- END PROCESS P2;
- P3: PROCESS(CLK)
- VARIABLE COUNTER : INTEGER RANGE 0 TO 1000;
- BEGIN
- TEM_TUBE_SIX <= TUBE_SIX;
- TEM_TUBE_FIVE <= TUBE_FIVE;
- TEM_TUBE_FOUR <= TUBE_FOUR;
- TEM_TUBE_THREE <= TUBE_THREE;
- TEM_TUBE_TWO <= TUBE_TWO;
- TEM_TUBE_ONE <= TUBE_ONE;
-
- IF (
- TEM_TUBE_ONE = "1000000" AND TEM_TUBE_TWO = "1000000" AND TEM_TUBE_THREE = "1000000" AND TEM_TUBE_FOUR = "1000000" AND TEM_TUBE_FIVE = "0100100" AND TEM_TUBE_SIX = "1111001"
- ) THEN
- COUNTER := 0;
- TEM_TIME_CLOCK <= '0';
- FLAG <= '1';
- ELSIF (
- TEM_TUBE_ONE = "1000000" AND TEM_TUBE_TWO = "1000000" AND TEM_TUBE_THREE = "1000000" AND TEM_TUBE_FOUR = "1000000" AND TEM_TUBE_FIVE = "1000000" AND TEM_TUBE_SIX = "1000000"
- ) THEN
- COUNTER := 0;
- TEM_TIME_CLOCK <= '0';
- FLAG <= '1';
- ELSIF FLAG = '1' THEN
- IF CLK'EVENT AND CLK = '1' THEN
- COUNTER := COUNTER + 1;
- END IF;
- IF COUNTER = 1000 THEN
- TEM_TIME_CLOCK <= '1';
- FLAG <= '0';
- END IF;
- END IF;
- END PROCESS P3;
-
- TIME_CLOCK <= TEM_TIME_CLOCK;
- END ONE;
9、原理图连接:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。