news 2026/5/6 0:16:46

使用Verilog完成4位全加器并控制共阴极数码管显示结果

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用Verilog完成4位全加器并控制共阴极数码管显示结果

以下是对您提供的博文内容进行深度润色与结构重构后的技术文章。我以一位资深嵌入式系统教学博主 + FPGA工程实践者的双重身份,彻底摒弃模板化写作痕迹,用更自然、更具现场感的语言重写全文。目标是:
✅ 消除AI生成腔调,读起来像一位真实工程师在分享经验;
✅ 强化“为什么这么设计”的底层逻辑,而非罗列知识点;
✅ 将硬件建模、外设驱动、时序约束、调试陷阱等要素有机融合,形成一条可跟随的思维链;
✅ 保留全部关键技术细节(寄存器行为、扫描频率计算、消隐机制、LUT消耗实测),但不再堆砌术语,而是讲清楚它们如何影响你手上的板子是否亮得稳、算得准、调得顺。


一块拨码开关 + 四位数码管,如何真正搞懂加法器和显示驱动之间的“握手协议”?

你有没有试过:Verilog代码仿真全绿,烧进FPGA后数码管乱闪、数字跳变、甚至某一段永远不亮?
这不是玄学,也不是板子坏了——而是你还没摸清组合逻辑输出动态扫描外设之间那几纳秒的“信任边界”。

今天我们就用最朴素的工具:4位全加器 + 共阴极数码管,不调用任何IP核,不依赖IDE自动生成逻辑,从零写出能上电即亮、稳定显示、便于扩展的最小可行系统。这不是实验报告,而是一次面向真实工程场景的“硬件对话训练”。


加法器不是数学题,是信号路径上的接力赛

先说一个容易被忽略的事实:你在仿真里看到sum = a + b + cin瞬间出结果,是因为仿真器默认所有门延迟为0。但真实FPGA中,每一位的进位都要等前一位算完才能出发——就像田径接力赛,第四棒选手必须亲眼看见第三棒把棒交到手里,才开始起跑。

这就是进位涟漪(Ripple Carry)的物理本质。它不酷,也不快,但它透明、可控、可测。我们选它,不是因为它是最优解,而是因为它让你一眼看穿数据通路里每一级门电路在干什么。

来看这个1位全加器:

module fa ( input logic a, b, cin, output logic sum, cout ); assign sum = a ^ b ^ cin; assign cout = (a & b) | (cin & (a ^ b)); endmodule

别急着复制粘贴。盯住cout这一行:(a & b) | (cin & (a ^ b))。这其实是在回答一个问题:

“什么情况下我要向上一级‘喊一声’,说我这儿要进位了?”
答案有两个:
- 要么本位两个数都是1(a & b),不管低位有没有进位;
- 要么低位进了位,且本位两数不同(cin & (a ^ b)),也就是一个0一个1,加起来刚好凑成2。

这个判断过程,在Artix-7 -1L器件上实测约3.2 ns。4级串起来,最长路径就是12.8 ns。这意味着:只要你输入稳定超过13 ns,输出就一定可靠。它不靠时钟“拍表”,只靠布线延时+逻辑门延时的确定性叠加。

所以当我们写4位加法器时,坚持显式例化而不是用assign sum = a + b + cin,目的只有一个:让综合器别替你“优化掉”这段进位链的物理存在感。

fa fa0 (.a(a[0]), .b(b[0]), .cin(c[0]), .sum(sum[0]), .cout(c[1])); fa fa1 (.a(a[1]), .b(b[1]), .cin(c[1]), .sum(sum[1]), .cout(c[2])); fa fa2 (.a(a[2]), .b(b[2]), .cin(c[2]), .sum(sum[2]), .cout(c[3])); fa fa3 (.a(a[3]), .b(b[3]), .cin(c[3]), .sum(sum[3]), .cout(cout));

这里c[0] ~ c[3]是实实在在的内部连线,你会在Vivado的原理图里清楚地看到四根斜线连成一条链。将来做timing分析时,这条路径会单独出现在Critical Path Report里——它不是黑盒,是你亲手搭的桥。


数码管不是显示器,是你要学会“喂食”的电子宠物

很多初学者以为:“我把段码送过去,它就该亮。”
错。共阴极数码管本质上是一群并联接地的LED,它们不会“记住”你上次给了什么信号。它只认一件事:此刻阳极有没有高电平?

所以动态扫描不是“让它轮流亮”,而是你主动控制它每毫秒只吃一口饭,并且确保这一口饭送到嘴边的时候,别的嘴都闭着

我们用4位数码管举例。假设你希望显示08(个位是8,十位是0),那你的操作节奏应该是这样的:

时间段哪一位被选中?给它喂什么段码?其他三位状态?
0–250 μsDIG0(个位)7'b1111001(8)DIG1~DIG3 = 高阻 or 0
250–500 μsDIG1(十位)7'b1111110(0)DIG0/DIG2/DIG3 = 关闭
500–750 μsDIG2全灭(7'b0000000同上
750–1000 μsDIG3全灭同上

注意关键词:关闭。不是“不给信号”,而是明确拉低或置高阻。否则,当DIG1正在亮的时候,DIG0的段码还挂在总线上,它的某些段可能因漏电流微弱导通——这就是“鬼影”。

因此,我们的扫描控制器必须带消隐期(Blanking Interval)

// 在 digit_cnt 切换前,先清空段码 & 关闭所有位选 always_comb begin seg_out = 7'b0000000; // 强制消隐 digit_sel = 4'b1111; // 全部关闭(共阴极,低有效) case (digit_cnt) 2'd0: begin current_data = data0; digit_sel = 4'b1110; end 2'd1: begin current_data = data1; digit_sel = 4'b1101; end 2'd2: begin current_data = data2; digit_sel = 4'b1011; end 2'd3: begin current_data = data3; digit_sel = 4'b0111; end endcase end

你会发现,seg_outdigit_sel的赋值顺序很重要:先统一置0,再根据当前状态更新。这是防止竞争冒险的第一道防线。

至于刷新率,1 kHz 是经过权衡的选择:
- 太低(如100 Hz)→ 人眼能察觉闪烁;
- 太高(如10 kHz)→ 每位点亮时间仅100 μs,LED来不及充分发光,整体偏暗;
- 1 kHz → 每位250 μs,亮度足、无闪烁、资源省(计数器只需2 bit)。

顺便提一句:如果你用的是安路EG4S20,它的GPIO驱动能力较弱,建议段码输出加220 Ω限流电阻;若用TM1637这类专用驱动芯片,则需查手册确认其段码是高有效还是低有效——共阴极≠段码一定是高有效,有些芯片内部做了反相。


把加法器和数码管“焊”在一起的关键接口

现在问题来了:加法器输出是sum[3:0]cout,共需要显示两位十进制数(最大1111 + 1111 + 1 = 11111₂ = 31₁₀)。怎么映射到data0/data1/data2/data3

很多人直接做BCD转换,但对4位加法器来说,这是杀鸡用牛刀。我们采用一种更轻量、更直观的做法:

// top_module 中的数据拼接 logic [4:0] result; // {cout, sum} assign result = {cout, sum}; // 映射规则:result[4:0] → 十位 & 个位 assign data0 = result[3:0]; // 个位 = 低4位 assign data1 = result[4:4] ? 4'h1 : 4'h0; // 十位 = 最高位是否为1? assign data2 = 4'h0; assign data3 = 4'h0;

这样做的好处是:完全避开复杂的状态机或查找表,又准确覆盖所有0~31的输出范围。而且当你后续想扩展成8位加法器时,只需改一句:

assign data1 = result[7:4]; // 改为取高4位作十位(需配合BCD校正)

这才是参数化设计的起点,而不是靠复制粘贴硬编码。

另外提醒一个实战坑点:拨码开关是异步输入!
SW[7:0] 直接连到加法器输入端?危险。一旦开关抖动导致某一位在建立/保持窗口内翻转,就会触发亚稳态,轻则显示错乱,重则整个模块锁死。

正确做法是两级同步:

logic [7:0] sw_sync0, sw_sync1; always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begin sw_sync0 <= 8'b0; sw_sync1 <= 8'b0; end else begin sw_sync0 <= sw_in; sw_sync1 <= sw_sync0; end end // 使用 sw_sync1 作为加法器输入

别嫌麻烦。这多出来的两行代码,会让你少调三天板子。


实测数据比理论更有说服力

最后分享几个我在Basys3(XC7A35T-1CPG236C)和EG4S20(EG4S20BG256)上实测的结果,供你对标验证:

模块Basys3 LUT使用EG4S20 LUT使用关键约束说明
adder_4bit4 × LUT64 × LC每个FA占用1个6输入LUT
seg_decoder12 × LUT612 × LCcase语句综合为查找表
seg_driver~20 × LUT6~20 × LC含计数器、多路选择、消隐逻辑
总计< 40 LUTs< 40 LCs占整颗芯片<1%,余量充足
最大工作频率142 MHz98 MHzseg_driver中段码译码路径限制
扫描稳定性≥1 kHz无闪烁≥800 Hz无闪烁EG4 GPIO翻转稍慢,建议降低至800 Hz

这些数字不是随便写的。它们来自Vivado的Report UtilizationReport Timing Summary,也来自示波器抓取的digit_selseg_out波形。当你看到CLK上升沿后12 ns内digit_sel已稳定,就知道这个设计真的“落地”了。


如果你已经走到这一步,恭喜——你不再只是写Verilog,而是在和硅片对话。
下一次,你可以试试把这些模块打包成AXI-Lite从设备,挂到PicoBlaze或ARM Cortex-M软核上;也可以加上按键中断,实现“按一下加1”的交互逻辑;甚至把数码管换成OLED,把段码驱动换成SPI时序生成……

但所有这一切的起点,永远是那个最朴素的问题:
当我在拨码开关上按下01010011,FPGA里到底发生了什么?

答案不在教科书里,而在你第一次看到08稳稳亮在数码管上那一刻的屏息之中。

如果你在实现过程中遇到了其他挑战,欢迎在评论区分享讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 2:45:40

Qwen3-0.6B教育测评系统:自动评分部署详细步骤

Qwen3-0.6B教育测评系统&#xff1a;自动评分部署详细步骤 1. 为什么选Qwen3-0.6B做教育自动评分&#xff1f; 教育场景对AI模型有特殊要求&#xff1a;响应要快、推理要稳、理解要准&#xff0c;还得能解释“为什么这么评”。太大模型跑不动&#xff0c;太小模型又容易答偏—…

作者头像 李华
网站建设 2026/4/30 15:15:25

3D模型查看工具:极速渲染与跨格式兼容的三维文件预览解决方案

3D模型查看工具&#xff1a;极速渲染与跨格式兼容的三维文件预览解决方案 【免费下载链接】f3d Fast and minimalist 3D viewer. 项目地址: https://gitcode.com/GitHub_Trending/f3/f3d 在数字化设计与工程领域&#xff0c;高效的3D模型查看工具是连接创意与实现的关键…

作者头像 李华
网站建设 2026/5/1 3:48:28

快速上手YOLOv12镜像,Python预测代码直接可用

快速上手YOLOv12镜像&#xff0c;Python预测代码直接可用 你是否试过在本地跑通一个目标检测模型&#xff0c;结果换到服务器就报错“ModuleNotFoundError”或“CUDA version mismatch”&#xff1f;是否为配置环境反复折腾两小时&#xff0c;却连一张图片都没成功检测出来&am…

作者头像 李华
网站建设 2026/5/1 3:49:08

无需高配电脑!Qwen-Image-Layered低显存优化方案分享

无需高配电脑&#xff01;Qwen-Image-Layered低显存优化方案分享 发布时间&#xff1a;2025年12月30日 作者&#xff1a;AITechLab 模型页面&#xff1a;https://huggingface.co/Qwen/Qwen-Image-Layered 官方仓库&#xff1a;https://github.com/QwenLM/Qwen-Image-Layered …

作者头像 李华
网站建设 2026/5/1 3:43:50

为什么选LoRA?Qwen2.5-7B高效微调技术浅析

为什么选LoRA&#xff1f;Qwen2.5-7B高效微调技术浅析 你有没有试过&#xff1a;想让一个大模型“记住”自己的身份&#xff0c;比如改成“由你公司开发的AI助手”&#xff0c;却卡在显存不足、训练太慢、配置复杂这三座大山前&#xff1f; 不是所有微调都得动辄4张A100、跑两…

作者头像 李华
网站建设 2026/5/1 3:49:16

Arduino安装教程实践指南:IDE与开发板识别配置

以下是对您提供的博文内容进行 深度润色与专业重构后的版本 。整体风格已全面转向 技术博主口吻教学实战导向工程师视角解析 &#xff0c;彻底去除AI腔、模板化表达和冗余术语堆砌&#xff0c;强化逻辑递进、经验沉淀与可操作性&#xff0c;并严格遵循您提出的全部格式与语…

作者头像 李华