用FPGA复刻经典数电实验:手把手教你实现一个带预置功能的十进制可逆计数器

张开发
2026/4/19 2:46:13 15 分钟阅读

分享文章

用FPGA复刻经典数电实验:手把手教你实现一个带预置功能的十进制可逆计数器
用FPGA复刻经典数电实验手把手教你实现一个带预置功能的十进制可逆计数器记得大学时第一次在实验箱上搭建十进制计数器看着LED灯随着时钟信号跳动的那种兴奋感吗如今一块FPGA开发板就能重现这份经典体验还能赋予它更多可能性。本文将带你用Verilog语言在Quartus II平台上完整实现一个支持数据预置、双向计数、使能控制的智能计数器让课本上的状态图真正跑起来。1. 需求分析与架构设计传统实验箱 vs FPGA实现的差异就像手动组装家具和3D打印的区别。前者需要逐根连线后者通过代码描述功能。我们的计数器需要实现以下核心功能双向计数通过upd信号控制递增/递减模式同步预置当load有效时下一个时钟沿将data[3:0]的值载入计数器使能控制en信号为高电平时才允许计数进位输出计数到9递增模式或0递减模式时产生进位脉冲模块接口设计如下建议保存为dec_counter.vmodule dec_counter ( input wire clk, // 时钟信号建议接50MHz input wire rst, // 异步复位低有效 input wire en, // 计数使能 input wire load, // 同步预置使能 input wire upd, // 计数方向1递增0递减 input wire [3:0] data,// 预置数据输入 output reg [3:0] q, // 计数输出 output reg co // 进位/借位信号 );2. Verilog实现与关键代码解析2.1 核心计数逻辑计数器的灵魂在于状态转移。采用同步时序设计所有操作都在时钟上升沿触发always (posedge clk or negedge rst) begin if (!rst) begin q 4b0000; // 异步复位 co 1b0; end else if (load) begin q data; // 同步预置 co 1b0; end else if (en) begin case ({upd, q}) 5b1_1001: begin // 递增到9 q 4b0000; co 1b1; end 5b0_0000: begin // 递减到0 q 4b1001; co 1b1; end default: begin q upd ? q 1 : q - 1; co 1b0; end endcase end end代码亮点使用case语句清晰表达状态转移条件进位信号co只在临界状态9→0或0→9产生单周期脉冲所有信号变化严格同步于时钟边沿2.2 仿真测试技巧编写测试平台时建议采用分层激励法。先创建基础时钟再逐步添加控制信号initial begin // 初始化 rst 0; en 0; load 0; upd 1; data 4b0000; #20 rst 1; // 释放复位 // 测试递增计数 #30 en 1; #200 en 0; // 测试预置功能 #20 load 1; data 4b0110; #20 load 0; // 测试递减模式 #20 upd 0; en 1; #200 $stop; end仿真要点复位后先验证递增计数是否正常预置值建议选择非边界值如6以验证加载功能切换计数方向时观察过渡是否平滑3. 硬件部署与调试3.1 引脚分配策略根据Cyclone IV EP4CE6开发板资源推荐配置信号名开发板对应器件引脚号备注clk50MHz晶振PIN_88全局时钟输入rst按键KEY0PIN_24低电平复位en按键KEY1PIN_31按下使能计数load按键KEY3PIN_33按下加载预置值upd拨码SW2PIN_30上拨递增下拨递减data[3]拨码SW7PIN_44预置值高位data[0]拨码SW4PIN_32预置值低位q[3:0]LED3-LED0PIN_54-46二进制计数显示coLED4PIN_58进位指示灯布局技巧时钟信号必须分配到专用时钟引脚关键控制信号使用按键状态信号使用拨码开关LED显示按二进制权重顺序排列q[3]对应LED33.2 上板验证流程静态测试设置load1通过SW7-SW4输入不同值检查LED3-LED0是否准确显示预置值动态测试设置en1upd1观察递增计数当计数到9时确认LED4短暂亮起切换upd0验证递减功能边界测试在计数到9时快速切换方向测试使能信号en的实时响应4. 高级优化技巧4.1 时钟去抖动处理机械按键会产生抖动添加如下消抖模块module debounce ( input clk, input btn_in, output reg btn_out ); reg [19:0] counter; always (posedge clk) begin if (btn_in ! btn_out) counter counter 1; else counter 0; if (counter) btn_out btn_in; end endmodule参数调整20位计数器约实现20ms消抖50MHz时钟对rst、en、load等关键信号都应进行消抖4.2 可视化改进将二进制输出转换为七段数码管显示module bin2seg ( input [3:0] bin, output reg [6:0] seg ); always (*) begin case (bin) 4d0: seg 7b1000000; 4d1: seg 7b1111001; // ... 2-8省略 4d9: seg 7b0010000; default: seg 7b1111111; endcase end endmodule4.3 资源优化报告编译后查看Quartus的Flow Summary资源类型使用量总量利用率Logic Elements2862720.45%Registers8--Memory Bits0276K0%优化空间如果不需要预置功能可节省约30%逻辑资源共享消抖计数器可减少硬件开销5. 教学延伸与实践尝试给计数器添加这些扩展功能自动方向切换当检测到上下限时自动反转计数方向速度调节通过PLL生成不同频率的计数时钟预设记忆用FPGA的嵌入式存储器保存多个预置值调试时遇到计数异常可以检查仿真波形确认逻辑正确性用SignalTap II抓取实际信号逐步降低时钟频率定位时序问题

更多文章