Repository navigation
zh getting started clock and input
目标:把上一页的普通算式替换成一个有时钟的 DUT,检查“加上 3”和“空闲时不变”。
本教程的 8 位累加器初始值为 0,每个上升沿查看一次输入:
-
enable=1:接受一个operand,更新total = (total + operand) % 256。 -
enable=0:不接受输入,total保持原值。 - 每次接受还会在 两周期后给出一个响应;本页先读
total,第 5 步再检查响应。
这里没有背压或 ready/valid 握手。enable 是这个练习 DUT 的明确输入规则,
不是 Toffee 对硬件协议的假设。把它保持为 1 两个上升沿,就会接受两次。
仓库提供 examples/getting_started/toy_dut.py,你可以直接使用 TutorialDut()。
它是 Python 写的教学替身,无需编译 RTL;初学时不用先理解它如何实现后端。
你需要知道的接口只有:
| 名称 | 用法 |
|---|---|
dut.operand.Set(3) |
把操作数写成 3;输入范围 0~255 |
dut.enable.Set(1) / .Set(0)
|
允许 / 停止下一上升沿接受 |
dut.total.U() |
读取当前无符号整数值 |
dut.clock |
等待周期时使用的时钟 |
dut.backend |
交给 Execution 推进这个 DUT |
dut.close() |
释放这个教学环境 |
dut 是一个变量名;句点表示访问它的某个成员。TutorialDut() 每次创建一个全新的
累加器实例。这个“初值为零”由教学替身提供;真实设计的初始化要按其规格实现。
下面是 examples/getting_started/test_accumulator.py 中本节新增的部分;前面章节的定义继续保留:
import pytest
from examples.getting_started.toy_dut import TutorialDut
from toffee import ClockCycles, Execution
@pytest.mark.asyncio
async def test_one_input_and_idle():
dut = TutorialDut()
try:
async with Execution(dut.backend):
assert dut.total.U() == 0
dut.operand.Set(3)
dut.enable.Set(1)
await ClockCycles(dut.clock, 1)
dut.enable.Set(0)
assert dut.total.U() == 3
await ClockCycles(dut.clock, 2)
assert dut.total.U() == 3
finally:
dut.close()python3 -m pytest -q examples/getting_started/test_accumulator.py::test_one_input_and_idle预期 1 passed。
import 从其他文件或包取得名字。@pytest.mark.asyncio 告诉 pytest 下面是一个
需要异步运行的测试;async def 允许函数里写 await。这里 await 是等待仿真条件,
不是让真实时间睡眠一秒。
async with Execution(dut.backend): 启动一个仿真环境,并在离开缩进块时退出它。
await ClockCycles(dut.clock, 1) 等待该时钟的下一个上升沿采样完成,随后才能读稳定结果。
没有这些等待,普通 Python 赋值本身不会让时钟前进。
try ... finally 表示:不管测试通过还是中途断言失败,都执行最后的 dut.close()。
本页先把这些环境代码写全,等它们重复出现时再介绍如何提取。
| 时刻 | enable | 发生的事 | total |
|---|---|---|---|
| 创建 DUT | 0 | 初始状态 | 0 |
| 第一上升沿前 | 1 | 测试把 operand 写为 3 | 0 |
| 第一上升沿 | 1 | DUT 接受一次 3 | 3 |
| 第一上升沿后 | 0 | 测试撤下 enable | 3 |
| 第二、第三上升沿 | 0 | 没有新输入 | 3 |
读懂这个表,再做一次小实验:注释掉 dut.enable.Set(0),重跑测试。
最后会得到 assert 9 == 3,因为 3 被加了三次。恢复该行后应重新通过。
这里的“周期”不是 Python 循环次数。后面的诊断还会显示 tick:当前后端一周期是
两个 half-tick,新时钟的第一上升沿为 tick 2。
内容由 CI 自动同步;请编辑主仓库文档。 Automatically synced by CI; edit the source documentation.
- 首页
- 教程
- 操作指南
- 参考
- 原理说明
- Home
-
Tutorials
- Learning path
- 0. Prepare your environment
- 1. Your first PASS and FAIL
- 2. Inputs and clocks
- 3. More cases and boundaries
- 4. Extract a Driver
- 5. Delayed output and a Monitor
- 6. Assemble an Agent
- 7. Models and the test environment
- 8. Pipelines, batches, and cancellation
- 9. Understand failures
- 10. Functional coverage
- Optional: out-of-order responses
- Optional: native clocks and project DUTs
-
How-to guides
- Find your task
- Simulation and events
- Verification components
- Coverage and regressions
- Migration and maintenance
- Runnable examples
- Reference
- Explanation