1. 设计目标
- 实现 24 小时制数字时钟的基本计时功能(时:分:秒)
- 通过 8 位数码管显示时间,格式为 HH.MM.SS
- 支持按键调整时间(秒、分、时分别可调)
- 拓展:本设计实现闹钟功能,可设置闹钟时间并在指定时间触发蜂鸣器报警
2. 开发流程
2.1 开发环境
| 目标器件 | EP4CE10F17C8 (Altera Cyclone IV) | | 开发工具 | Quartus II 13.0 | | 系统时钟 | 50MHz 晶振 | | 编程语言 | Verilog HDL |
2.2 架构设计
为了提供一种最简单直观的显示,开发板上提供了一个 7 段 8 位共阳极数码管电路。为了减少对 FPGA 引脚资源的占用,开发板上的数码管采用串行移位寄存器芯片将串行数据转化为 16 位并行数据后进行驱动。Cyclone IV E 通过 3 根数据线,连接到两片级联的串行移位器芯片 74HC595 上,再由 74HC595 将每次 16 位串行的数据转化为 16 位并行的数据,分别用以驱动 7 段 8 位数码管的段选和位选。

top 顶层模块,负责各子模块的连接与信号分配(top.v)
Project_Segled2 数字时钟核心模块,包含计时、显示、按键处理、闹钟等功能(Project_Segled2.v)
HC595_Driver 74HC595 移位寄存器驱动,实现串行数据输出(HC595_Driver.v)
2.3 顶层 IO
module top(
input Clk, // 50MHz 系统时钟
input Rst_n, // 复位信号(低电平有效)
input KEY1, // 模式切换/长按进入闹钟设置
input KEY2, // 数值递增按键
output SH_CP, // 74HC595 移位时钟
output ST_CP, // 74HC595 锁存时钟
output DS, // 74HC595 串行数据
output BEEP // 蜂鸣器输出
);
2.4 数字时钟核心模块 (Project_Segled2.v)
2.4.1 按键消抖
采用计数器消抖方式,消抖时间约 20ms:
parameter DB_CNT_MAX = 20'd100; // 消抖计数最大值
// 两级同步 + 计数消抖
always @(posedge CLK_50M or negedge RST_N) begin
if(!RST_N) begin
k1_sync0 <= 1'b1;
k1_sync1 <= 1'b1;
end else begin
k1_sync0 <= FLAG1;
k1_sync1 <= k1_sync0;
end
end
设计特点:
- 采用两级触发器同步,防止亚稳态
- 检测高→低电平翻转,产生单周期脉冲
- 支持长按检测(1 秒),用于进入闹钟设置模式
2.4.2 计时
基于 50MHz 时钟进行分频,实现秒、分、时的计时:
// 关键参数
parameter SET_TIME_1S = 'd50_000_000; // 1 秒计数值
parameter SIXTY = 'd60; // 60 进制
parameter TWENTYFORE = 'd24; // 24 进制
// 1 秒定时器
always @ (posedge CLK_50M or negedge RST_N) begin
if(!RST_N)
cnt_1s <= 28'd0;
else if(set_mode != 2'd0) // 调整模式下暂停
cnt_1s <= 28'd0;
else if(cnt_1s == SET_TIME_1S - 1)
cnt_1s <= 28'd0;
else
cnt_1s <= cnt_1s + 28'b1;
end
计时进位逻辑:
- 秒:0-59 循环,满 60 进位
- 分:0-59 循环,满 60 进位
- 时:0-23 循环,满 24 复位
2.4.3 时间调整模式状态机
通过按键切换四种工作模式:
| 模式值 | 模式名称 | 功能描述 |
|---|---|---|
| 0 | 正常模式 | 时钟正常走时 |
| 1 | 调秒模式 | 秒位闪烁,可调整秒 |
| 2 | 调分模式 | 分位闪烁,可调整分 |
| 3 | 调时模式 | 时位闪烁,可调整时 |
always @(posedge CLK_50M or negedge RST_N) begin
if(!RST_N)
set_mode <= 2'd0;
else if(mode_pulse && !alarm_set_mode && !alarm_triggered)
set_mode <= set_mode + 2'd1; // 0→1→2→3→0 循环
end
2.4.4 闹钟功能
闹钟设置流程:
- 长按 KEY1(1 秒)进入闹钟设置模式
- 短按 KEY1 切换时/分设置位置
- 按 KEY2 递增当前设置值
- 再次长按 KEY1 退出设置并使能闹钟
// 闹钟触发检测
always @(posedge CLK_50M or negedge RST_N) begin
if(!RST_N)
alarm_triggered <= 1'b0;
else if(alarm_triggered && (mode_pulse || inc_pulse))
alarm_triggered <= 1'b0; // 任意按键取消
else if(alarm_enabled && !alarm_set_mode &&
cnt_h == alarm_h && cnt_m == alarm_m && cnt_s == 6'd0)
alarm_triggered <= 1'b1; // 时间匹配,触发闹钟
end
报时特性:
- 闪烁 6 次(300ms 周期)
- 蜂鸣器间歇发声
2.4.5 数码管显示
采用动态扫描方式驱动 8 位数码管:
// 显示格式:HH-MM-SS
// 位置分配:7-6-5-4-3-2-1-0
// 时十位 - 时个位 - 横线 - 分十位 - 分个位 - 横线 - 秒十位 - 秒个位
// 1ms 扫描周期
parameter SET_TIME_1MS = 16'd50_000;
// 段码查找表(共阴极数码管)
parameter SEG_CODE_0 = 8'b1100_0000,
SEG_CODE_1 = 8'b1111_1001,
...,
SEG_CODE_9 = 8'b1001_0000,
SEG_CODE_DASH = 8'b1011_1111; // 横线"-"
二进制转 BCD 算法(Double Dabble):
// 将 6 位二进制数转换为 2 位 BCD
for(i = 5; i >= 0; i = i - 1) begin
if (s_ones >= 4'd5) s_ones = s_ones + 4'd3;
if (s_tens >= 4'd5) s_tens = s_tens + 4'd3;
s_tens = {2'b00, s_tens[2:0], s_ones[3]};
s_ones = {2'b00, s_ones[2:0], cnt_s[i]};
end
2.4.6 蜂鸣器控制
生成约 2kHz 方波驱动蜂鸣器:
parameter BEEP_FREQ_CNT = 16'd12500; // 50MHz/12500/2 = 2kHz
always @(posedge CLK_50M or negedge RST_N) begin
if(!RST_N)
beep_cnt <= 16'd0;
else if(beep_cnt >= BEEP_FREQ_CNT - 1) begin
beep_cnt <= 16'd0;
beep_tone <= ~beep_tone;
end else
beep_cnt <= beep_cnt + 16'd1;
end
2.5 74HC595 驱动模块 (HC595_Driver.v)
2.5.1 74HC595 芯片简介
74HC595 是一款 8 位串入并出移位寄存器,具有以下特点:
- 串行数据输入,8 位并行数据输出
- 具有输出锁存功能
- 可级联扩展
2.5.2 引脚功能
| 引脚 | 名称 | 功能 |
|---|---|---|
| DS | 数据输入 | 串行数据输入端 |
| SH_CP | 移位时钟 | 上升沿移入数据 |
| ST_CP | 锁存时钟 | 上升沿锁存数据到输出 |
2.5.3 驱动时序设计
parameter DATA_WIDTH = 16; // 16 位数据(8 位段码 + 8 位位选)
parameter CNT_MAX = 4; // 分频系数
// 移位时钟生成
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
divider_cnt <= 16'd0;
else if(divider_cnt == CNT_MAX)
divider_cnt <= 16'd0;
else
divider_cnt <= divider_cnt + 1'b1;
assign sck_pluse = (divider_cnt == CNT_MAX);
2.5.4 时序状态机
case(SHCP_EDGE_CNT)
5'd0: begin SH_CP <= 1'b0; ST_CP <= 1'b1; DS <= r_data[15]; end
5'd1: begin SH_CP <= 1'b1; ST_CP <= 1'b0; end
5'd2: begin SH_CP <= 1'b0; DS <= r_data[14]; end
5'd3: begin SH_CP <= 1'b1; end
// ... 依次移出 16 位数据
5'd30: begin SH_CP <= 1'b0; DS <= r_data[0]; end
5'd31: begin SH_CP <= 1'b1; end
endcase
3 系统功能说明
3.1 操作说明
| 操作 | 按键 | 功能说明 |
|---|---|---|
| 模式切换 | 短按 KEY1 | 正常→调秒→调分→调时→正常 循环 |
| 数值调整 | 按 KEY2 | 在调整模式下,递增当前选中位 |
| 进入闹钟设置 | 长按 KEY1(1 秒) | 进入闹钟时间设置模式 |
| 切换闹钟设置位 | 短按 KEY1 | 在闹钟设置模式下切换时/分 |
| 设置闹钟值 | 按 KEY2 | 递增闹钟时间 |
| 退出闹钟设置 | 长按 KEY1(1 秒) | 保存并使能闹钟 |
| 取消闹钟 | 按任意键 | 闹钟响时按任意键停止 |
3.2 状态指示
| 状态 | 显示效果 |
|---|---|
| 正常计时 | 全部数字稳定显示 |
| 调秒模式 | 秒位闪烁(250ms 周期) |
| 调分模式 | 分位闪烁(250ms 周期) |
| 调时模式 | 时位闪烁(250ms 周期) |
| 闹钟设置 | 被调整位闪烁,秒显示 00 |
| 整点报时 | 全部闪烁 6 次(300ms 周期),蜂鸣器间歇响 |
| 闹钟触发 | 全部快速闪烁(125ms 周期),蜂鸣器持续响 |
