用户设计接入指南
这份指南面向只开发一个设计的普通用户。用户只需要给设计起名、编写 RTL 和测试, 不需要选择 design ID,也不需要修改 designs/registry.json。最终 ID 由维护者合并 代码时分配。
完整示例:
1. 检查工具
需要 Python 3、GNU Make、C++ 编译器和 Verilator。推荐 Verilator 5.050,工程也 验证过 5.032;低于 5.032 的版本未验证。
make verilator-version2. 创建设计
选择一个能表达功能的名称,例如 counter32:
make create-design DESIGN_NAME=counter32命令会创建:
designs/counter32/
├── README.md
├── README.en.md
├── design.json
├── rtl/Counter32.sv
└── tests/
├── Counter32Tb.sv
└── FrameCounter32Tb.sv默认模块名由设计名称生成。确实需要自定义时使用:
make create-design DESIGN_NAME=counter32 DESIGN_MODULE=MyCounter创建命令不会覆盖已有目录。名称只能使用小写字母、数字、点、下划线和连字符。
3. 编写电路
打开 rtl/Counter32.sv,替换模板逻辑。下面五个端口是 FrameTop 与用户设计之间 的固定接口,初次使用时不要改名或删除:
input logic clock;
input logic reset;
input logic [65:0] io_in;
output logic [65:0] io_out;
output logic [65:0] io_oe;clock:时钟;纯组合电路可以不使用,但端口必须保留。reset:复位;无状态电路可以不使用,但端口必须保留。io_in[n]:读取第 n 位用户 IO 的当前电平。io_out[n]:设计准备输出的值。io_oe[n] = 1:设计驱动该引脚;为 0 时释放该引脚。
请为全部 io_out 和 io_oe 位提供确定值。常见写法是先清零,再打开实际输出:
always_comb begin
io_out = '0;
io_oe = '0;
// 实际逻辑
end4. 修改测试
两个 TB 文件已经标出“通常保留”和“按设计修改”的区域:
tests/Counter32Tb.sv只测试用户电路;tests/FrameCounter32Tb.sv测试信号经过外部user_io和 FrameTop 的完整路径。
Frame TB 中的 DESIGN_ID 由构建工具通过 FRAME_TEST_DESIGN_ID 自动注入。不要 把它改成固定数字。
5. 运行用户检查
仓库中只有一个未注册设计时,不需要传入目录:
make user-lint
make user-test
make user-frame-test也可以一次运行全部检查:
make user-check这些命令分别完成:
user-lint:检查用户 RTL 语法、组合环路和常见结构问题;user-test:运行独立单元测试;user-frame-test:自动选择空闲临时 ID,生成隔离 registry,再运行 Frame TB。
如果工作区中有多个未注册设计,工具会要求显式选择:
make user-check DESIGN=designs/counter32原有维护者命令仍可使用,例如 make design-test DESIGN=designs/counter32 TEST=io。
6. IO 映射
FrameTop 的 73 根双向引脚中,低 7 位供框架选择设计,其余 66 位连接用户电路:
设计 io_*[n] <-> 外部 user_io[n + 7]例如 io_in[0] 对应 user_io[7]。测试环境只能驱动设计释放的输入引脚;如果 测试环境和设计同时驱动同一位,波形会出现 x。
7. 查看波形
make user-frame-test TRACE=1
gtkwave build/waves/counter32/frame.fst本次 Frame 测试实际使用的临时或正式 ID 写在:
build/designs/counter32/frame/selected-id.txt假设其中是 1,在 GTKWave 的 SST 窗口中展开:
FrameCounter32Tb
└── dut
└── u_design_registry
└── u_design_1
└── u_design重点观察 TB 的 test_io_out/test_io_oe/user_io、FrameTop 的 selection_valid/payload_*,以及最后一级 u_design 内部的状态信号。
io_in 会回读设计正在驱动的输出引脚,这是双向 IO 的正常行为。判断方向时以 io_oe 为准。
8. 提交代码
提交前运行:
make user-check
make docs-check
git diff --check
git status --short普通用户提交 designs/<name>/ 即可,不要修改或提交以下内容:
designs/registry.json;rtl/generated/FrameDesignRegistry.sv;build/和 FST 波形。
维护者合并时执行:
make integrate-design DESIGN=designs/counter32 DESIGN_ID=12该命令分配最终槽位、更新正式 registry、重新生成 registry RTL,并使用最终 ID 再次运行 Frame 测试。
常见错误
no unregistered user design found:当前没有待测试设计,先运行创建命令。multiple unregistered user designs found:使用DESIGN=designs/<name>指定。- 输出为
z:对应io_oe没有置 1,或设计尚未成功选中。 - 输出为
x:信号没有确定赋值,或 TB 与设计同时驱动同一引脚。 $fatal:TB 检查失败,错误文字会说明具体位置。generated file is stale:这是维护者正式集成阶段的问题,运行make registry-generate。