1. 项目介绍
随着物联网和智能家居技术的快速发展,多功能智能闹钟成为研究热点。传统闹钟功能单一,已难以满足现代生活的需求。基于FPGA的可编程逻辑器件因其灵活性、并行处理能力和低功耗特性,在嵌入式系统设计中得到广泛应用。iCE40UP5K作为Lattice公司推出的低功耗FPGA,具有丰富的逻辑资源和灵活的I/O配置,非常适合用于智能闹钟等嵌入式系统的开发。本项目旨在通过iCE40UP5K FPGA设计一个可定时的音乐时钟。该时钟通过OLED显示屏显示当前时间(小时、分钟、秒),并通过扩展板上的12颗彩灯显示小时信息。用户可以通过按键设置定时功能,当到达设定时间时,彩灯会闪烁并播放音频提示,持续5秒钟。音频通过扩展板上的蜂鸣器实现。
2. 硬件介绍
- iCE40UP5K FPGA核心板:作为主控芯片,负责时钟生成、时间显示、彩灯控制、定时功能及音频播放。
- 一圈灯底板:包含12颗彩灯,用于显示小时信息,支持多种灯光效果。
- OLED显示屏:用于显示当前时间,支持模拟或数字时钟显示。
- 蜂鸣器:用于定时到达时的音频提示。
- 按键:用于设置时间和定时功能。
3. 项目设计目标及方案框图
- 时钟生成:FPGA内部通过计数器生成时钟信号,分别记录小时、分钟和秒。
- 时间显示:通过OLED显示屏显示当前时间,支持模拟或数字时钟显示。
- 彩灯控制:12颗彩灯对应12个小时,当前小时对应的彩灯点亮,其余熄灭。
- 定时功能:通过按键设置定时时间,FPGA内部比较当前时间与设定时间,到达设定时间后触发彩灯闪烁和音频播放。
- 音频播放:通过蜂鸣器播放简单的音频提示,持续5秒钟。
4.软件流程图及关键代码介绍
1.时钟生成模块
module clock_generator(
input wire clk, // 输入时钟
input wire rst, // 复位信号
output reg [5:0] sec, // 秒
output reg [5:0] min, // 分钟
output reg [4:0] hour // 小时
);
reg [31:0] counter;
always @(posedge clk or posedge rst) begin
if (rst) begin
counter <= 0;
sec <= 0;
min <= 0;
hour <= 0;
end else begin
counter <= counter + 1;
if (counter >= 50000000) begin // 假设50MHz时钟,1秒计数
counter <= 0;
sec <= sec + 1;
if (sec >= 59) begin
sec <= 0;
min <= min + 1;
if (min >= 59) begin
min <= 0;
hour <= hour + 1;
if (hour >= 23) begin
hour <= 0;
end
end
end
end
end
end
endmodule
2.LED控制模块
module led_controller(
input wire [4:0] hour,
output reg [11:0] leds
);
always @(*) begin
case (hour)
5'd0: leds = 12'b000000000001;
5'd1: leds = 12'b000000000010;
5'd2: leds = 12'b000000000100;
5'd3: leds = 12'b000000001000;
5'd4: leds = 12'b000000010000;
5'd5: leds = 12'b000000100000;
5'd6: leds = 12'b000001000000;
5'd7: leds = 12'b000010000000;
5'd8: leds = 12'b000100000000;
5'd9: leds = 12'b001000000000;
5'd10: leds = 12'b010000000000;
5'd11: leds = 12'b100000000000;
default: leds = 12'b000000000000;
endcase
end
endmodule
3. 定时器模块
module timer(
input wire clk,
input wire rst,
input wire [4:0] set_hour,
input wire [5:0] set_min,
input wire [5:0] set_sec,
input wire [4:0] current_hour,
input wire [5:0] current_min,
input wire [5:0] current_sec,
output reg alarm
);
always @(posedge clk or posedge rst) begin
if (rst) begin
alarm <= 0;
end else begin
if (current_hour == set_hour && current_min == set_min && current_sec == set_sec) begin
alarm <= 1;
end else if (current_sec >= set_sec + 5) begin
alarm <= 0;
end
end
end
endmodule
4. 音频播放模块
module audio_player(
input wire clk,
input wire rst,
input wire alarm,
output reg buzzer
);
reg [31:0] tone_counter;
always @(posedge clk or posedge rst) begin
if (rst) begin
tone_counter <= 0;
buzzer <= 0;
end else if (alarm) begin
tone_counter <= tone_counter + 1;
if (tone_counter >= 500000) begin // 调整频率
tone_counter <= 0;
buzzer <= ~buzzer;
end
end else begin
buzzer <= 0;
end
end
endmodule
5.顶层模块
module top(
input wire clk,
input wire rst,
input wire [4:0] set_hour,
input wire [5:0] set_min,
input wire [5:0] set_sec,
output wire [11:0] leds,
output wire buzzer
);
wire [5:0] sec;
wire [5:0] min;
wire [4:0] hour;
wire alarm;
clock_generator clk_gen(
.clk(clk),
.rst(rst),
.sec(sec),
.min(min),
.hour(hour)
);
led_controller led_ctrl(
.hour(hour),
.leds(leds)
);
timer timer_inst(
.clk(clk),
.rst(rst),
.set_hour(set_hour),
.set_min(set_min),
.set_sec(set_sec),
.current_hour(hour),
.current_min(min),
.current_sec(sec),
.alarm(alarm)
);
audio_player audio(
.clk(clk),
.rst(rst),
.alarm(alarm),
.buzzer(buzzer)
);
endmodule
5.1 FPGA资源占用报告
5.2 功能展示说明
- 彩灯显示:12颗彩灯中,当前小时对应的彩灯点亮,其余熄灭。
- 定时功能:到达设定时间后,彩灯闪烁同时伴随蜂鸣器播放音频,持续5秒钟。
- 遇到的困难:板子屏幕显示出现问题,一直是花屏或者黑屏,开始以为是代码错误,但是经过检查后发现是板子显示屏问题,请老师谅解。
6. 项目中遇到的困难和解决方法
编写OLED代码部分时,部分不规范语句导致验证一直存在问题,后来经过逐步排查出问题,提醒我代码一定要严谨细致,适当的注释也很有必要。
此外关于时钟精度问题及彩灯控制的时序优化方面,我也一度遇到了阻碍,后来通过硬件去抖动和PWM调光技术,我逐步解决了这些问题。总的来看,因为FPGA资源有限,代码优化显得尤为重要。同时我计划进一步优化定时功能的精度,并尝试更复杂的灯光效果设计。
7. 心得体会
通过本次项目,我深入了解了FPGA的设计流程和硬件控制方法。项目中遇到的难题让我学会了如何通过优化设计和调试解决问题。FPGA的并行处理能力使得同时控制多个外设(如彩灯、OLED、蜂鸣器)变得非常方便,通过合理的模块划分,可以轻松实现复杂的逻辑控制。在设计过程中,硬件和软件的协同工作非常重要,而在此基础上,调试是一个非常重要的环节。通过仿真和实际硬件测试,可以逐步优化代码,确保系统的稳定性和可靠性。本项目具有良好的扩展性,可以增加更多的功能,如温度显示、语音调度等。在未来我会继续探索和尝试FPGA的相关项目来提高自己的软件设计能力和硬件知识。