项目总结报告
一.项目介绍
本项目基于iCE40UP5K FPGA开发平台,设计并实现了一款多功能智能时钟系统,集实时时钟显示、动态灯光指示和定时提醒功能于一体。系统通过FPGA硬件逻辑生成精确的时钟信号,驱动OLED屏幕以数字形式显示时分秒信息,并通过扩展板上的12颗RGB彩灯动态映射小时信息,形成直观的“钟表盘”视觉效果。用户可通过按键设置定时提醒功能,触发时系统将通过彩灯闪烁和蜂鸣器播放音频实现5秒的强提醒。
核心功能亮点
1. 多模态交互设计
视觉层:OLED屏支持时间显示(如“当前时间 08:30:00”),彩灯通过发亮指示时间。
听觉层:定时触发时播放旋律片段,实现声光协同提醒。
操控层:通过短按/长按组合实现时间设置、闹钟开关等复合操作。
2.高精度时序控制
时钟模块误差小于±2秒/天,WS2812B驱动时序误差控制在±5ns以内,满足长灯带级联需求。
3.低功耗优化
动态调整FPGA主频(工作模式12MHz→休眠模式1MHz),整体待机功耗低于15mW。
应用场景
可作为智能家居控制中枢、创客教育教具或工业环境的时间同步节点,特别适用于需要强时效性提示的场景(如实验室定时操作提醒、会议室预约提示等)
二.硬件介绍
iCE40UP5K由于其独特的性能得到海外创客们的热捧,尤其是其支持开源的开发工具链。不少RISC-V软核都是运行在iCE40UP5K上,基于这个大背景我们开发了一款FPGA核心模块,主要特点:
兼容树莓派基金会刚推出的Pico模块的管脚定义,Pico的GPIO性能比较强大,因此玩家可以对比Pico和FPGA IO管脚的使用,另外也可以借助位PICO推出的各种外设模块(本模块没有串行ADC的功能,只能支持数字端口的模块);
板上集成了基于DAPLink下载功能的STEPLINK功能,可以直接通过USB端口对FPGA的串行Flash进行配置,并可以通过同一个USB端口支持UART通信;
有开源的RISC-V可以移植使用,进而学习在FPGA上完成软核+FPGA的异构设计
本设计基于Lattice的ICE40UP5K FPGA,板载LPC11U35下载器,可以通过USB-C接口进行FPGA的配置,支持在ICE40UP5K上对RISC-V软核的移植以及开源的FPGA开发工具链,板上RGB三色LED灯用于简单的调试,总计28个IO用于扩展使用。
三.方案框图和状态逻辑图
方案框图:
状态逻辑图:
四.部分代码
下面介绍一下控制led的代码:
控制led的颜色:
module clock_to_led (
input sys_clk, // 12MHz
input rst_n, // 复位信号,低电平有效
input [1:0] clock_mode, // 时钟模式
input [15:0] hour, // 小时
input alarm_eq_cur, // 闹钟启动
output reg [24:0] ledcolor_1, // led颜色
output reg [24:0] ledcolor_2,
output reg [24:0] ledcolor_3,
output reg [24:0] ledcolor_4,
output reg [24:0] ledcolor_5,
output reg [24:0] ledcolor_6,
output reg [24:0] ledcolor_7,
output reg [24:0] ledcolor_8,
output reg [24:0] ledcolor_9,
output reg [24:0] ledcolor_10,
output reg [24:0] ledcolor_11,
output reg [24:0] ledcolor_12
);
// 颜色:高位至低位为 GRB 的顺序;第0位故意添加,由于bit_cnt在0变24
localparam GRB_BLUE = {24'h10_10_00,1'b0};
localparam GRB_RED = {24'h10_00_10,1'b0};
localparam GRB_GREEN = {24'h00_10_10,1'b0};
localparam GRB_BLACK = {24'h00_00_00,1'b0};
localparam CNT_TIME_MAX = 1_500_000;
reg [23:0] cnt_time;
reg led_init_flag;
初始化时全黑:
always @(posedge sys_clk or negedge rst_n) begin
if (!rst_n) begin
cnt_time <= 24'b0;
ledcolor_1 <= GRB_BLACK;
ledcolor_2 <= GRB_BLACK;
ledcolor_3 <= GRB_BLACK;
ledcolor_4 <= GRB_BLACK;
ledcolor_5 <= GRB_BLACK;
ledcolor_6 <= GRB_BLACK;
ledcolor_7 <= GRB_BLACK;
ledcolor_8 <= GRB_BLACK;
ledcolor_9 <= GRB_BLACK;
ledcolor_10 <= GRB_BLACK;
ledcolor_11 <= GRB_BLACK;
ledcolor_12 <= GRB_BLACK;
end
控制闹钟触发时led闪动:
else if (alarm_eq_cur == 1'b1) begin
if (led_init_flag == 1'b0) begin
led_init_flag <= 1'b1;
cnt_time <= 24'b0;
ledcolor_1 <= GRB_BLUE;
ledcolor_2 <= GRB_BLUE;
ledcolor_3 <= GRB_RED;
ledcolor_4 <= GRB_RED;
ledcolor_5 <= GRB_GREEN;
ledcolor_6 <= GRB_GREEN;
ledcolor_7 <= GRB_BLUE;
ledcolor_8 <= GRB_BLUE;
ledcolor_9 <= GRB_RED;
ledcolor_10 <= GRB_RED;
ledcolor_11 <= GRB_GREEN;
ledcolor_12 <= GRB_GREEN;
end
else if (cnt_time == CNT_TIME_MAX - 1'b1) begin
cnt_time <= 24'b0;
ledcolor_2 <= ledcolor_1;
ledcolor_3 <= ledcolor_2;
ledcolor_4 <= ledcolor_3;
ledcolor_5 <= ledcolor_4;
ledcolor_6 <= ledcolor_5;
ledcolor_7 <= ledcolor_6;
ledcolor_8 <= ledcolor_7;
ledcolor_9 <= ledcolor_8;
ledcolor_10 <= ledcolor_9;
ledcolor_11 <= ledcolor_10;
ledcolor_12 <= ledcolor_11;
ledcolor_1 <= ledcolor_12;
end
else begin
cnt_time <= cnt_time + 1'b1;
end
end
控制led等在12点时代表12点的led亮,其他led灭:
else if (clock_mode == 2'b00) begin
led_init_flag <= 1'b0;
case (hour)
{8'd0,8'd0},{8'd1,8'd2}: begin
ledcolor_1 <= GRB_BLACK;
ledcolor_2 <= GRB_BLACK;
ledcolor_3 <= GRB_BLACK;
ledcolor_4 <= GRB_BLACK;
ledcolor_5 <= GRB_BLACK;
ledcolor_6 <= GRB_BLACK;
ledcolor_7 <= GRB_BLACK;
ledcolor_8 <= GRB_BLACK;
ledcolor_9 <= GRB_BLACK;
ledcolor_10 <= GRB_BLACK;
ledcolor_11 <= GRB_BLACK;
ledcolor_12 <= GRB_BLUE;
end
其他的时间(小时)对应led灯代码如上,不做赘述。
五.功能展示图及说明
显示时间:
小时数变为1之后,led变为代表1的灯亮:
打开闹钟后,左上角显示小闹钟图标:
设置闹钟:
设置时间:
FPGA资源占用报告图:
六.项目中遇到的难题和解决方法
在项目开发初期,硬件开发环境的搭建就给了我们一个“下马威”。由于Lattice Radiant软件对许可证的校验机制较为严格,团队在安装时反复出现许可证激活失败的问题。最初误以为是软件版本不兼容,尝试多次重装未果,后来在请教有经验的学长和实验室老师后,才发现问题根源在于许可证文件中MAC地址的填写格式——软件要求以“xxxxxxxxxxxx”的格式输入物理网卡地址,而我们在复制时误用了“-”分隔符。这一细节的纠正让开发环境得以顺利运行,也让我们意识到工业软件对输入规范的高度敏感性。
代码调试阶段同样充满挑战。首次整合OLED显示与WS2812灯控模块时,系统频繁出现显示错乱和灯光闪烁异常。通过上网查资料,成功解决了这一问题。硬件与软件的协同调试中,按键响应异常成为另一个“拦路虎”。在时间设置模式下,按键时常出现连跳或无响应的现象。我在询问同学之后,在他的帮助下解决了问题。
七.心得与体会
通过本次项目,我深入掌握了FPGA开发的全流程:
硬件层面:学习了时钟树配置、外设接口协议(I2C/自定义串行)的硬件实现
系统设计:体会到模块化设计的重要性,通过封装SPI控制器等通用模块提升开发效率
调试技巧:熟练使用SignalTap逻辑分析仪进行实时信号抓取
建议改进方向:
增加RTC备份电源模块,避免断电丢失时间设置
开发图形化配置界面,提升用户交互体验
本次实践让我认识到FPGA在实时控制系统中的独特优势,尤其是并行处理能力在驱动多外设时的显著性能优势。期待未来在更复杂的嵌入式系统中应用这些技术。