2182 字
11 分钟
- 次浏览
数字系统实验多了以后,顶层最容易乱
读前导览

Verilog 综合实验里,模块单独能跑还不够。顶层选择、板卡资源复用和报告材料也得重新梳理。

正文
2182 字
阅读
11 分钟
结构
7 节
来源线索
GitLaughs/Verilogexp
Verilogexp:project_sum Verilogexp:project_top Verilogexp:数字系统实验

数字系统实验刚开始做的时候,成就感很直接。

LED 闪起来,计数器跑起来,数码管显示出数字,VGA 屏幕出现稳定图案。每个实验都像一个清楚的小岛:输入是什么,输出是什么,错了就顺着真值表、波形、状态机或引脚约束查下去。

但实验一多,问题会换一种形态。

后面更麻烦的是另一件事:这些模块放进同一个工程后,还能不能讲清楚、验出来、交出去。

这次综合工程就是这样的转折点。组合逻辑、流水灯、智能抢答器、交通灯、秒表、VGA 显示、呼吸灯、UART 串口环回,单独看都不算庞大;放到同一套板卡约束下,顶层就不再是一个空壳,而成了各个实验和板卡外设碰头的地方。

顶层先把资源归属说清楚#

课程实验里很容易把“综合工程”理解成“把所有模块例化一遍”。

顶层除了例化模块,还得把几件事交代清楚:

  • 当前到底在验证哪个实验。
  • 哪些输入在这个实验里有效。
  • 哪些外设由这个实验驱动。
  • 未被选中的实验应该输出什么默认状态。
  • 同一组 LED、数码管、VGA 或 UART 资源如何避免被多个模块同时驱动。

这些问题如果不在顶层回答,后面就会被上板现象逼着回答。

一个 LED 亮了,到底是流水灯亮的,还是交通灯状态机亮的?数码管显示错了,是抢答器的段码错了,还是交通灯倒计时还在抢同一组位选?VGA 没画面,是显示模块没跑起来,还是顶层根本没有把它选出来?

资源归属不清时,现象就会失去可解释性。

选择信号把实验入口固定下来#

这个综合工程最后用 sel[7:0] 做实验选择。

它是一个独热选择信号:同一时间只允许一个选择位有效。选中某一位时,对应实验的输出才接到板卡外设;没被选中的实验,即使内部还在随时钟运行,也不会拥有外设驱动权。

这个设计很朴素,但它把一件事写清楚了:当前板卡正在被哪个实验占用。

sel[0] 对应组合逻辑,sel[1] 对应流水灯,后面依次接抢答器、交通灯、秒表、VGA、呼吸灯和 UART。这样一来,切换实验不需要临时改顶层、不需要重新删模块,也不靠记忆某个“现在应该看哪个文件”的状态。

选择信号在这里承担的是入口管理:它说明这个综合工程收进了哪些实验。

有了这个入口,报告和 README 就能说清楚:哪些实验进了综合顶层,哪些实验仍然保留为独立材料,哪些现象应该在哪个选择位下观察。

板卡资源有限,复用必须有规则#

FPGA 实验板的外设资源是有限的,复用不可避免。

同一组按键,可以在组合逻辑里当数据输入,也可以在抢答器里当选手按键;同一个开关,可以在一个实验里当功能选择,在另一个实验里当显示模式;LED 可以显示组合逻辑结果,也可以显示流水灯状态、交通灯状态或呼吸灯 PWM 效果。

复用可以接受,但每一路外设最后归谁驱动,需要在顶层写明白。

在这个顶层里,规则集中体现在多路选择上:

sel -> 当前实验
当前实验输出 -> 对应外设
未选中实验 -> 不驱动外设或给出空闲默认值

右侧数码管只在抢答器和交通灯之间选择,左侧数码管只在秒表实验中有效。通用 LED 根据组合逻辑、流水灯和交通灯分支切换。VGA 只有在 VGA 实验被选中时才输出颜色和同步信号。UART 没被选中时,发送线保持空闲电平。

这类默认设置看起来不起眼,但后面排错很靠它。

很多上板问题看起来像模块坏了,实际常常是旁路没处理干净。未选择 VGA 时,同步信号不能乱跳;未选择 UART 时,发送线不该被拉成奇怪状态;未选择 LED 实验时,灯不该被残留信号点亮。

顶层越清楚,旁路越安静。

子模块保持独立,顶层负责调度#

我比较喜欢这个综合工程的一点,是它没有把每个实验的内部逻辑拆散重写。

组合逻辑仍然处理自己的编码器、比较器和全加器。流水灯仍然是自己的状态机。抢答器、交通灯、秒表、VGA、呼吸灯、UART 都保留各自的顶层或重点模块。综合顶层只在外面做三件事:

  1. 统一板级输入输出。
  2. 把共享输入分配给对应实验。
  3. 根据 sel 决定哪一路输出拥有外设。

这比把所有逻辑揉进一个巨大 always 稳得多。

子模块保持独立,后面才方便单独仿真、单独解释、单独替换。顶层调度清楚,上板验收和报告复查也会轻很多。课程实验做到后面,麻烦的地方往往是所有东西互相缠住,最后谁都不敢改。

不是所有实验都适合放进同一个顶层#

综合也不是越全越好。

有些实验适合集中到同一套板卡约束下,比如组合逻辑、流水灯、抢答器、交通灯、秒表、VGA、呼吸灯和 UART。它们都可以通过开关选择后在板卡上直接观察。

但有些实验保留独立材料更合理。比如以触发器和计数器波形观察为主的内容,更适合放在仿真工程里;MicroBlaze 和 Vitis 软件实验也不必强行塞进普通 Verilog 综合顶层。

这些内容分开放,反而更好查、更好讲。

能集成的就集成,应该独立的就独立。课程仓库没必要把所有目录折叠成一个入口,每个实验放在合适的位置更好维护。

交付时别只留下 bitstream#

做课程实验时,很容易把交付理解成“板子能跑”和“报告能交”。

但实验数量一多,复查时更容易卡在这些地方:源码在哪里,约束文件是哪份,顶层模块叫什么,哪些实验已经进了综合工程,哪些波形和图片能对应到报告,哪些目录只是 Vivado 生成的缓存。

所以我更愿意把交付拆成两层。

第一层是能重新打开和综合的重点文件:Verilog 源码、约束、工程入口、必要脚本、报告用图片和说明文档。

第二层是可以再生成的过程成果:综合缓存、实现中间目录、临时仿真输出、日志、bitstream、波形数据库。这些东西可以留在本地,但不该成为仓库主要内容。

这样整理以后,工程就不再停留在“我这台机器上曾经跑通过”,而是隔一段时间以后也能按说明重新打开、综合、验证。

课程后半段练的是整理能力#

回头看,project_top 最有用的地方,是把分散实验收到了一个能讲清楚的入口里。

它做的事情很朴素:选择唯一,外设归属清楚,默认输出干净,子模块还保持独立,综合工程也能和报告对上。

这件事不华丽,但很像数字系统课程后半段最后要练的东西。

单个模块能跑以后,多个模块放在一起还能被解释、被复查、被交付,才开始有工程味道。

硬件设计不像脚本那样可以靠“先跑起来再说”糊过去。错误的连线、含糊的默认设置、没有声明的资源复用,都会在上板时变成很具体的异常现象。越往后做,越会发现:能跑还不够,还要能解释、能复现,也要写清楚哪些东西不能同时占用。

所以这篇回看最后想记下的是一个很朴素的判断:

实验多起来后,顶层先理清楚,后面的报告和复查才不会乱。

数字系统实验多了以后,顶层最容易乱
https://blog.sunmmyapi.xyz/posts/verilog-project-top-before-many-experiments/
作者
Sun
发布于
2026-05-29
许可协议
CC BY-NC-SA 4.0

继续读

相关内容