Начните с наблюдаемого поведения
Для небольшого RTL-блока определите входную транзакцию, выходной результат и допустимую задержку. Попросите ИИ составить тестовую матрицу из спецификации: сброс, обычный обмен, граничные значения и остановки передачи. Не передавайте только реализацию и просьбу «написать тесты»: тест может повторить ту же ошибку. Сначала сформулируйте независимую эталонную модель.
Выберите правильный момент чтения
Фронт тактового сигнала и установившиеся выходы — разные события модели симуляции. Для чтения итоговых значений текущего шага можно дождаться ReadOnly после фронта, как показано ниже. Это фрагмент внутри асинхронного теста с тактом dut.clk. После ReadOnly не записывайте сигналы в том же шаге; планируйте драйвер отдельно от монитора.
from cocotb.triggers import RisingEdge, ReadOnly
await RisingEdge(dut.clk)
await ReadOnly()
# Sample settled outputs here.Сделайте отказ явным
Сравнивайте результат с эталоном через утверждения, добавляйте ограничение времени ожидания и считайте принятые транзакции. Сообщение в журнале само по себе не проваливает тест. Проверяйте, что монитор действительно увидел обмен, а не завершился без наблюдений. Для случайного стимула сохраняйте seed, последовательность входов и первую несовпавшую транзакцию.
Сохраните регрессионный сценарий
Запишите версии cocotb и симулятора, список HDL-файлов, верхний модуль и параметры. После исправления повторите исходный сценарий и соседние граничные случаи. Просите ИИ уменьшить падающий тест, сохраняя критерий отказа. Результат — воспроизводимый отчёт и самопроверяющийся тест. Отдельно проверяйте RTL средствами lint и синтеза: симуляция покрывает только исполненные сценарии.
Что проверить перед принятием результата
Хороший тест обнаруживает ошибку, объясняет несовпадение и повторяется с теми же входами.