Начните с наблюдаемого поведения

Для небольшого RTL-блока определите входную транзакцию, выходной результат и допустимую задержку. Попросите ИИ составить тестовую матрицу из спецификации: сброс, обычный обмен, граничные значения и остановки передачи. Не передавайте только реализацию и просьбу «написать тесты»: тест может повторить ту же ошибку. Сначала сформулируйте независимую эталонную модель.

Выберите правильный момент чтения

Фронт тактового сигнала и установившиеся выходы — разные события модели симуляции. Для чтения итоговых значений текущего шага можно дождаться ReadOnly после фронта, как показано ниже. Это фрагмент внутри асинхронного теста с тактом dut.clk. После ReadOnly не записывайте сигналы в том же шаге; планируйте драйвер отдельно от монитора.

python
from cocotb.triggers import RisingEdge, ReadOnly

await RisingEdge(dut.clk)
await ReadOnly()
# Sample settled outputs here.

Сделайте отказ явным

Сравнивайте результат с эталоном через утверждения, добавляйте ограничение времени ожидания и считайте принятые транзакции. Сообщение в журнале само по себе не проваливает тест. Проверяйте, что монитор действительно увидел обмен, а не завершился без наблюдений. Для случайного стимула сохраняйте seed, последовательность входов и первую несовпавшую транзакцию.

Сохраните регрессионный сценарий

Запишите версии cocotb и симулятора, список HDL-файлов, верхний модуль и параметры. После исправления повторите исходный сценарий и соседние граничные случаи. Просите ИИ уменьшить падающий тест, сохраняя критерий отказа. Результат — воспроизводимый отчёт и самопроверяющийся тест. Отдельно проверяйте RTL средствами lint и синтеза: симуляция покрывает только исполненные сценарии.

Что проверить перед принятием результата

Хороший тест обнаруживает ошибку, объясняет несовпадение и повторяется с теми же входами.

Источники