用Verilog在DE2-115上实现一个带暂停/清零的百分秒表(Quartus 13.1完整工程)

发布时间:2026/6/2 2:10:04

用Verilog在DE2-115上实现一个带暂停/清零的百分秒表(Quartus 13.1完整工程) 基于DE2-115开发板的百分秒表FPGA实战开发指南第一次接触FPGA开发时最令人兴奋的莫过于让硬件真正动起来。本文将带您从零开始在DE2-115开发板上实现一个功能完整的百分秒表包含暂停和清零功能。不同于教科书式的理论讲解这里将重点分享实际工程中那些容易踩坑的细节——从Quartus 13.1工程配置到数码管驱动原理每个步骤都经过真实硬件验证。1. 工程准备与环境搭建1.1 Quartus 13.1工程创建要点在开始编写Verilog代码前正确的工程配置能避免后续许多麻烦。新建工程时需特别注意器件选择DE2-115开发板搭载的是Cyclone IV EP4CE115F29C7文件命名规范建议采用stopwatch_top.v作为顶层文件名避免中文和特殊字符仿真工具设置默认使用ModelSim-Altera需确保路径不含空格提示Quartus 13.1对Windows 10的兼容性需要特别注意建议以管理员身份运行软件1.2 开发板硬件资源确认DE2-115开发板上的关键资源分配如下表所示资源类型具体配置本实验用途时钟源50MHz晶振系统主时钟数码管共阳极4位时间显示按键KEY[0]-KEY[3]清零/暂停控制LEDLEDG[0]-LEDG[7]状态指示2. 核心模块设计与实现2.1 精准分频电路设计DE2-115提供的50MHz时钟需要分频为100Hz驱动百分秒表。传统分频方式存在累积误差改进方案如下module clock_divider ( input wire clk_50m, input wire reset_n, output reg clk_100hz ); reg [31:0] counter; localparam DIVIDER 500000; // 50MHz/100Hz always (posedge clk_50m or negedge reset_n) begin if (!reset_n) begin counter 0; clk_100hz 0; end else if (counter DIVIDER/2 - 1) begin clk_100hz ~clk_100hz; counter 0; end else counter counter 1; end endmodule关键改进点采用50%占空比分频确保计时精度32位计数器设计避免溢出风险异步复位确保可靠初始化2.2 可暂停的计数逻辑实现暂停功能通过控制计数器的使能信号实现比中断时钟更可靠module decimal_counter ( input wire clk, input wire reset_n, input wire pause, output reg [3:0] units, output reg [3:0] tens, output wire carry ); always (posedge clk or negedge reset_n) begin if (!reset_n) begin units 0; tens 0; end else if (!pause) begin if (units 9) begin units 0; if (tens 9) tens 0; else tens tens 1; end else units units 1; end end assign carry (units 9) (tens 9); endmodule3. 数码管驱动与显示优化3.1 共阳极数码管驱动原理DE2-115采用共阳极数码管与常见开发板有所不同。显示数字0的段码对应关系段位abcdefg电平0000001引脚6543210对应的Verilog译码器实现module seg7_decoder ( input wire [3:0] bcd, output reg [6:0] seg ); always (*) begin case (bcd) 4d0: seg 7b1000000; 4d1: seg 7b1111001; // ...其他数字编码 default: seg 7b1111111; endcase end endmodule3.2 显示刷新与消隐技术为避免数码管闪烁推荐采用扫描刷新方式设计1kHz的刷新时钟依次激活每位数码管同步输出对应段码每位显示保持1msmodule display_scan ( input wire clk, input wire [6:0] seg0, seg1, seg2, seg3, output reg [3:0] anode, output reg [6:0] cathode ); reg [1:0] sel; always (posedge clk) begin sel sel 1; case (sel) 2b00: begin anode 4b1110; cathode seg0; end // 其他位选择逻辑 endcase end endmodule4. 系统集成与调试技巧4.1 顶层模块接口设计完整系统接口定义示例module stopwatch_top ( input wire CLOCK_50, input wire [1:0] KEY, output wire [6:0] HEX0, HEX1, HEX2, HEX3, output wire [7:0] LEDG ); // 内部信号声明 wire clk_100hz; wire [3:0] min_units, min_tens; wire [3:0] sec_units, sec_tens; // 模块实例化 clock_divider u_divider ( .clk_50m(CLOCK_50), .reset_n(KEY[0]), .clk_100hz(clk_100hz) ); // 其他模块连接... endmodule4.2 常见问题排查指南实际开发中可能遇到的问题及解决方案数码管显示乱码检查共阳极/共阴极配置验证段码顺序是否与硬件匹配测量各引脚电平是否正常计时不准确认分频系数计算正确检查时钟约束是否添加使用SignalTap观察实际时钟波形按键抖动问题添加硬件消抖电路或在Verilog中实现软件消抖典型消抖延时20ms为宜5. 功能扩展与进阶优化5.1 多模式计时功能实现通过状态机扩展秒表功能typedef enum { MODE_STOP, MODE_RUN, MODE_LAP } stopwatch_mode; module mode_controller ( input wire clk, input wire reset_n, input wire mode_btn, output stopwatch_mode mode ); // 状态转换逻辑... endmodule5.2 数据存储与回放利用DE2-115的SDRAM存储计时记录设计存储控制状态机分配缓冲区地址空间实现读写时序控制添加数据校验机制module record_ctrl ( input wire clk, input wire save_trig, input wire [15:0] time_data, output reg [21:0] sdram_addr, inout wire [15:0] sdram_data ); // SDRAM控制器实现... endmodule在完成基础功能后尝试添加这些扩展功能能让项目更具挑战性。实际开发中建议先通过仿真验证各模块功能再逐步进行硬件测试。遇到问题时分段调试往往比整体排查更有效率——可以先单独测试分频器输出再验证计数器逻辑最后整合显示部分。

相关新闻