FPGA时钟设计
实现功能:基于Verilog的动态显示时钟设计,支持整点(时:00:00)闪烁功能。代码包含时钟计数、动态扫描、整点检测和闪烁控制模块:
module dynamic_clock(input clk, // 主时钟(假设50MHz)input rst_n, // 异步复位(低电平有效)output reg [7:0] seg, // 数码管段选(a-g + dp)output reg [3:0] dig // 数码管位选(共4位,显示时:分)
);// 内部信号定义
reg [25:0] cnt_div; // 分频计数器
reg [3:0] scan_cnt; // 扫描计数器
reg [1:0] blink_ctrl; // 闪烁控制
reg [5:0] sec, min, hour; // 时间计数器(0-59, 0-59, 0-23)
wire clk_1k; // 扫描时钟(1kHz)
wire clk_1hz; // 1Hz时钟
wire clk_2hz; // 2Hz闪烁时钟
wire blink_en; // 闪烁使能信号// 分频模块:生成1kHz扫描时钟和1Hz基准时钟
assign clk_1k = cnt_div[17]; // 50MHz/(2^18) ≈ 190Hz(实际需调整至1kHz)
assign clk_1hz = cnt_div[25]; // 50MHz/(2^26) ≈ 1.49Hz(需校准至精确1Hz)always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt_div <= 0;else cnt_div <= cnt_div + 1;
end// 时间计数模块
always @(posedge clk_1hz or negedge rst_n) beginif(!rst_n) beginsec <= 0;min <= 0;hour <= 0;end else beginsec <= (sec == 59) ? 0 : sec + 1;if(sec == 59) beginmin <= (min == 59) ? 0 : min + 1;if(min == 59) beginhour <= (hour == 23) ? 0 : hour + 1;endendend
end// 整点检测与闪烁控制(每分钟0秒时闪烁)
assign blink_en = (min == 0) && (sec < 10); // 每分钟前10秒检测
assign clk_2hz = cnt_div[24]; // 约2Hz闪烁频率always @(posedge clk_2hz or negedge rst_n) beginif(!rst_n) blink_ctrl <= 0;else if(blink_en) blink_ctrl <= ~blink_ctrl;else blink_ctrl <= 2'b11; // 非闪烁时段常亮
end// 动态扫描模块
always @(posedge clk_1k or negedge rst_n) beginif(!rst_n) beginscan_cnt <= 0;dig <= 4'b1111;end else beginscan_cnt <= scan_cnt + 1;case(scan_cnt[1:0])2'b00: dig <= 4'b1110; // 显示小时十位2'b01: dig <= 4'b1101; // 显示小时个位2'b10: dig <= 4'b1011; // 显示分钟十位2'b11: dig <= 4'b0111; // 显示分钟个位endcaseend
end// BCD转七段码(共阴数码管)
always @(*) beginif(blink_ctrl[0]) seg = 8'hff; // 闪烁时关闭显示else case({dig, scan_cnt[1:0]})// 小时十位4'b1110: seg = (hour >= 20) ? 8'h86 : // 显示"2"(hour >= 10) ? 8'hc0 : // 显示"1"8'hff; // 不显示// 小时个位4'b1101: seg = bcd_to_seg(hour % 10);// 分钟十位4'b1011: seg = bcd_to_seg(min / 10);// 分钟个位4'b0111: seg = bcd_to_seg(min % 10);default: seg = 8'hff;endcase
end// BCD转换函数
function [7:0] bcd_to_seg;input [3:0] num;begincase(num)0: bcd_to_seg = 8'hc0; // 01: bcd_to_seg = 8'hf9; // 12: bcd_to_seg = 8'ha4; // 23: bcd_to_seg = 8'hb0; // 34: bcd_to_seg = 8'h99; // 45: bcd_to_seg = 8'h92; // 56: bcd_to_seg = 8'h82; // 67: bcd_to_seg = 8'hf8; // 78: bcd_to_seg = 8'h80; // 89: bcd_to_seg = 8'h90; // 9default: bcd_to_seg = 8'hff;endcaseend
endfunctionendmodule
关键设计说明:
-
时钟分频:
- 使用计数器生成1Hz基准时钟(精确计时需要校准)
- 生成1kHz扫描时钟用于动态显示
- 2Hz信号用于控制闪烁频率
-
时间计数器:
- 秒计数器(0-59)
- 分计数器(0-59)
- 时计数器(0-23)
- 自动进位逻辑
-
动态扫描:
- 4位数码管显示(时十位、时个位、分十位、分个位)
- 位选信号循环扫描(1kHz频率)
-
整点闪烁:
- 检测每分钟的0秒时刻(
min==0 && sec<10
) - 使用2Hz信号控制显示开关(亮灭各0.25秒)
- 闪烁期间段选信号强制为全灭(
8'hff
)
- 检测每分钟的0秒时刻(
-
显示处理:
- 小时十位智能显示(>=20显示2,>=10显示1)
- BCD转七段码译码器
- 冒号处理(示例代码未包含,可通过dp点扩展)
扩展建议:
- 精确计时:
// 校准50MHz到精确1Hz(需根据实际时钟频率修改)
parameter DIV_1HZ = 50_000_000; // 50MHz时钟
reg [25:0] cnt_1hz;always @(posedge clk or negedge rst_n) beginif(!rst_n) begincnt_1hz <= 0;clk_1hz <= 0;end else if(cnt_1hz == DIV_1HZ-1) begincnt_1hz <= 0;clk_1hz <= ~clk_1hz;end else begincnt_1hz <= cnt_1hz + 1;end
end
- 添加设置功能:
- 增加按键输入接口
- 实现时间调整模式
- 长按/短按区分设置
- 声音提示:
// 整点报时模块示例
reg buzzer;
always @(posedge clk_1hz) beginbuzzer <= (sec == 0) && (min == 0) && (hour < 23);
end
- 显示优化:
- 添加冒号闪烁(每秒一次)
- 低电量指示
- 12/24小时制切换
该设计需要配合硬件开发板(如FPGA)上的数码管电路实现,实际使用时需根据具体硬件调整位选和段选的极性(共阴/共阳)。