当前位置: 首页 > news >正文

基于Logisim与Verilog HDL的运动码表计时电路设计与DE2-70开发板验证

1. 从零开始理解运动码表计时电路

第一次接触数字电路设计时,看到"运动码表计时电路"这个概念可能会觉得有点高大上。其实说白了,这就是一个能记录分钟和秒钟的计时器,跟我们平时用的秒表功能差不多。只不过这次我们要用Logisim画电路图,再用Verilog HDL写代码,最后在DE2-70开发板上跑起来。

这个项目最有趣的地方在于,它完美展示了数字电路设计的完整流程:从逻辑设计到硬件实现。我刚开始做这个项目时,对着真值表画电路图画到怀疑人生,但后来看到数码管上的数字正常跳动时,那种成就感真的无法形容。

计时电路的核心是四个计数器:分的十位(0-5)、分的个位(0-9)、秒的十位(0-5)、秒的个位(0-9)。这就像我们平时看时间的习惯一样,只不过在电路里是用二进制实现的。特别要注意的是进位信号的处理——低位的进位信号就是高位的时钟信号,这个设计思路非常巧妙。

2. Logisim电路设计实战

2.1 BCD码计数器设计

在Logisim里设计BCD码计数器是第一个难点。我建议先搞定0-9的十进制计数器,再改造成0-5的六进制计数器。具体来说,一个完整的BCD码计数器需要两部分:

  1. 状态转换电路:控制0到9的状态切换
  2. 输出函数电路:在状态从9跳回0时产生进位信号

画电路图时有个小技巧:先列出真值表,然后用Logisim的"组合分析"功能自动生成电路。这比手动连线省事多了,特别适合我们这些新手。不过自动生成的电路可能不够优化,后期可以手动调整。

记得我第一次做的时候,忘了处理进位信号,结果计数器到9就卡住了。后来发现是输出函数没设计好,当计数器从9变0时,必须输出一个高电平的进位信号。

2.2 完整计时电路搭建

四个计数器都做好后,就要考虑它们之间的连接了。这里的关键是:

  • 秒的个位(0-9)计数器:时钟直接接外部时钟
  • 秒的十位(0-5)计数器:时钟接秒个位的进位
  • 分的个位(0-9)计数器:时钟接秒十位的进位
  • 分的十位(0-5)计数器:时钟接分个位的进位

在Logisim中测试时,建议先用快速时钟信号(比如1Hz)观察计数过程。我第一次测试时用了太快的时钟,结果数字跳得眼花缭乱,根本看不清是否正确进位。后来改用慢速时钟,配合单步调试,才确认电路工作正常。

3. Verilog HDL实现

3.1 十进制计数器模块

用Verilog写计数器比画电路图简单多了。下面是我调试通过的十进制计数器代码:

module bcd_counter1( input en_10, // 使能信号 input clk_10, // 时钟信号 input res_10, // 复位信号 input zin_10, // 进位输入 output zout_10, // 进位输出 output reg [3:0] qout_10 // 计数输出 ); always@(posedge clk_10) begin if(res_10) qout_10 <= 4'b0; // 复位时清零 else if(en_10) if(qout_10 == 4'h9) qout_10 <= 4'b0; // 到9后归零 else if(zin_10) qout_10 <= qout_10 + 1'b1; // 正常计数 end assign zout_10 = (qout_10 == 4'h9); // 产生进位信号 endmodule

这个模块有几个关键点:

  1. 使用posedge clk_10确保在时钟上升沿触发
  2. 复位信号高电平有效
  3. 只有在使能信号有效且收到进位信号时才计数

3.2 六进制计数器模块

秒的十位需要0-5的六进制计数器,代码与十进制类似,但判断条件不同:

module bcd_counter2( input en_6, input clk_6, input res_6, input zin_6, output zout_6, output reg [3:0] qout_6 ); always@(posedge clk_6) begin if(res_6) qout_6 <= 4'b0; else if(en_6) if(qout_6 == 4'h5) // 注意这里是5不是9 qout_6 <= 4'b0; else if(zin_6) qout_6 <= qout_6 + 1'b1; end assign zout_6 = (qout_6 == 4'h5); // 到5时进位 endmodule

3.3 顶层模块设计

顶层模块负责把四个计数器连接起来:

module jishiqi( input en, input clk, input res, output [15:0] D_count_16 ); wire mone_mten_out; // 秒个位→秒十位 wire mten_fone_out; // 秒十位→分个位 wire fone_ften_out; // 分个位→分十位 bcd_counter1 mone( .en_10(en), .clk_10(clk), .res_10(res), .zin_10(1'b1), // 秒个位始终允许计数 .zout_10(mone_mten_out), .qout_10(D_count_16[3:0]) ); bcd_counter2 mten( .en_6(en), .clk_6(clk), .res_6(res), .zin_6(mone_mten_out), .zout_6(mten_fone_out), .qout_6(D_count_16[7:4]) ); // 其他两个计数器类似... endmodule

4. DE2-70开发板验证

4.1 引脚分配

在Quartus II中,需要为输入输出信号分配实际引脚。根据DE2-70开发板的硬件布局,我使用了以下配置:

  • SW0:使能信号(en)
  • SW1:复位信号(res)
  • KEY0:手动时钟(clk)
  • HEX0-HEX3:分别显示秒个位、秒十位、分个位、分十位

引脚分配完成后,记得生成编程文件(.sof)。我第一次下载时忘了分配引脚,结果开发板上的数码管完全没反应,排查了好久才发现问题。

4.2 实际测试技巧

在开发板上测试时,建议:

  1. 先用慢速手动时钟(KEY0)测试进位关系
  2. 确认基本功能正常后,再改用50MHz系统时钟分频得到1Hz时钟
  3. 观察从59秒到1分钟的跳变是否正确
  4. 测试复位功能是否正常工作

我在测试时发现秒十位偶尔会显示6,检查后发现是六进制计数器的判断条件写成了"=="而不是">=",导致在快速时钟下可能错过复位时机。这个小bug让我深刻理解了异步电路设计的注意事项。

5. 常见问题与调试技巧

做这个项目时,我踩过不少坑,这里分享几个常见问题:

  1. 计数器不工作:检查时钟极性是否正确,复位信号是否有效
  2. 进位不正常:确认低位计数器的进位输出确实连接到了高位计数器的时钟输入
  3. 显示乱码:检查数码管译码电路是否正确,特别是BCD码到七段码的转换
  4. 计时不准:如果是用高频时钟分频,检查分频计数器是否足够大

调试时建议分模块验证:先单独测试每个计数器,再测试进位关系,最后整合整个系统。用SignalTap II逻辑分析仪可以很方便地观察内部信号变化。

6. 项目扩展思路

基础功能实现后,可以尝试以下扩展:

  1. 添加暂停/继续功能
  2. 实现多组计时记忆
  3. 增加报警功能(如计时到设定时间时触发)
  4. 改用更精确的时钟源(如开发板上的50MHz晶振分频)

我在完成基础功能后,增加了通过VGA显示大号数字的功能。虽然花了不少时间调试,但看到计时器在大屏幕上显示时,感觉特别有成就感。这些扩展不仅能提升项目复杂度,也能让你更深入地理解FPGA开发。

http://www.jsqmd.com/news/593195/

相关文章:

  • 告别繁琐下载:File Browser极简方案实现20+格式文件在线预览
  • t3mujinpack胶片模拟技术解析:基于Hald CLUT算法的开源胶片仿真实现
  • 如何系统化解决戴森球计划黑雾威胁:从自动化防御到资源管理的蓝图方案
  • Gin 框架进阶系列(六):Gin 认证与授权——JWT 鉴权实战
  • 2026年教育学论文降AI工具推荐:教学设计和调研分析部分如何降 - 还在做实验的师兄
  • 计算机毕业设计:Python二手车全栈数据洞察与价格预测系统 Django框架 可视化 线性回归 数据分析 机器学习 深度学习 AI 大模型(建议收藏)✅
  • dfs序
  • 3分钟学会OpenSpeedy游戏加速:免费开源打破帧率限制的终极指南
  • 如何用SillyTavern在5分钟内创建你的第一个AI虚拟伙伴?
  • Gin 框架进阶系列(七):Gin 统一响应与错误处理最佳实践
  • res-downloader:全平台网络资源下载工具的高效使用指南
  • 效果-Horizon 无限视界
  • Gin 框架进阶系列(零)
  • 2026年中医药论文降AI工具推荐:病案记录和方剂分析部分怎么处理 - 还在做实验的师兄
  • Gin 框架进阶系列(八):Web 安全攻防——原理、攻击与防御实践
  • AutoUnipus:智能刷课助手终极指南,2025年实现U校园全自动答题
  • Gin 框架进阶系列(三):请求处理
  • 实战避坑:用V4L2 API在RK3568上稳定获取IMX415摄像头码流的5个关键步骤
  • Ni8mare高危漏洞来袭:黑客可远程劫持n8n服务器(CVE-2026-21858)
  • D8 242. 移除链表元素
  • Scarab重构空洞骑士模组管理:智能依赖解析与自动化安装的革新实践
  • 提升游戏开发效率:用快马平台一键生成小恐龙游戏高质量基础模板
  • 2026年哪些写作习惯最容易被AIGC误判:特征分析和规避方法 - 还在做实验的师兄
  • 告别药物研发效率困境:用REINVENT4实现智能分子设计范式突破
  • OpenClaw 对接微信机器人配置全教程:从 0 到 1 搭建个人 AI 助手
  • Gin 框架进阶系列(四):中间件机制深入
  • 论文不同章节降AI策略不同:分章节精准处理的完整教程 - 还在做实验的师兄
  • 告别重复造轮子:用快马AI一键生成嵌入式驱动与协议栈代码
  • 大众点评数据采集终极指南:15分钟搭建智能爬虫系统
  • STM32入门——实时时钟(20)