Карточка 9. Синтез на Verilog
Паспорт концепта
- Уровни: 35 «Центр вычислений (АЛУ)» (30 мин), 36 «ALU» (40 мин), 37 «Память и Время» (30 мин), 38 «Шаг за шагом» (25 мин), 39 «Оперативная память» (30 мин), 40 «Сердце процессора» (40 мин), 41 «Анатомия системы» (35 мин), 42 «Рентген для кремния» (20 мин), 43 «Остановка времени» (35 мин). Часть 3.
- Суммарно: ~285 минут игры, обычно 6–7 занятий. Блок повторяет весь курс (сумматор, регистр, RAM, процессор) уже на текстовом языке — темп выше, потому что идеи знакомы.
- Результаты обучения: ученик пишет модуль Verilog с порта и инстанцированием; отличает комбинационную логику (always, assign) от последовательностной (по фронту clk); использует generate-for для шин; объясняет иерархию модулей и читает осциллограмму, находя задержку распространения.
- Гайды: ур. 35, ур. 36, ур. 37, ур. 38, ур. 39, ур. 40, ур. 41, ур. 42, ур. 43.
План занятия на 45 минут
Первое занятие блока: уровни 35–36 (АЛУ на Verilog). Дальше — по одному-два уровня за занятие: 37–38, 39, 40–41, 42–43.
- 0–10 мин. Разминка: чем текстовое описание схемы лучше перетаскивания вентилей? Пусть ученики назовут два преимущества: повторяемость (generate) и читаемость (имена сигналов).
- 10–25 мин. Уровень 35 самостоятельно: модуль с портами, первый always-блок. Типичная точка застревания — не забыть вход в списке портов; показывайте, как редактор подсвечивает ошибки.
- 25–35 мин. Разбор уровня 37: почему у памяти есть clk, а у АЛУ нет. Ключевая фраза занятия: «такт нужен для запоминания, а не для вычисления».
- 35–45 мин. Уровень 36 в парах (роли — ниже). Домашний кусок: уровень 37 целиком; тем, кто застрял, — только наводящая подсказка. Готового кода в игре больше нет: подсказка вставляет каркас с двумя вырезанными строками Mux, их ученики дописывают сами.
Вопросы для обсуждения
- Что описывает строка `module adder8(out, a, b)` — физический объект или его интерфейс? Где тогда «внутренности»?
- Почему АЛУ можно написать без clk, а регистр — нельзя? Что случится с регистром без такта?
- generate-for разворачивается в восемь одинаковых DFF. Чем это лучше ручного копирования восьми строк, а чем хуже?
- RAM256 — «чёрный ящик». Почему интерфейс важнее внутренностей? Приведите пример из обычного программирования.
- CPU инстанцирует Reg8 и FullAdder — что произойдёт физически при синтезе? Это «вызов функции» или что-то другое?
- На осциллограмме Carry опоздал относительно Sum. Почему тест на фронте такта ловит это, а «на глаз» в схеме из вентилей — нет?
Ожидаемые ошибки
Список собран из неверных вариантов концепт-чеков уровней 37, 39, 41 и 43; на уровнях 35–36, 38, 40, 42 концепт-чеков нет — пункты по ним собраны из типичных ошибок и будут уточняться по телеметрии.
- Ученик говорит: «память медленнее АЛУ, поэтому ей нужен clk, чтобы успеть». Реакция: дело не в скорости. АЛУ считает постоянно, а триггер обязан зафиксировать значение в конкретный момент — на фронте, — иначе запишет шум промежуточных состояний.
- Ученик говорит: «Clock отключает АЛУ между тактами для экономии энергии». Реакция: АЛУ вычисляет непрерывно; тактового отключения в курсе нет. Такт — про момент записи, не про питание.
- Ученик говорит: «RAM256 скрыт, потому что код зашифрован». Реакция: код открыт и доступен кликом. Абстракция в том, что на этом уровне внутренности не нужны — важен только интерфейс портов.
- Ученик говорит: «CPU вызывает модули по очереди, как функции». Реакция: в железе нет вызовов. Инстанцирование — постоянное соединение частей: Reg8 и FullAdder сидят внутри CPU и работают одновременно.
- Ученик говорит: «Carry опоздал — это ошибка симулятора». Реакция: это реальный эффект. Путь переноса проходит через больше вентилей, чем путь суммы; задержка распространения — свойство схемы, и осциллограмма его честно показывает.
Критерии оценки
- Собрал. Уровни 35–43 закрыты, все тесты зелёные.
- Собрал и объяснил. Объясняет разницу комбинационной и последовательностной логики своими словами, читает осциллограмму и находит на ней причину падения теста.
- Перенёс на новую задачу. Пишет свой модуль (например, счётчик с загрузкой) без гайда; или объясняет, почему 8-битный перенос в его синтезированной схеме медленнее суммы и как это увидеть на временной диаграмме.
Задача для сильных
Возьмите full_adder.v из уровня 43 и перепишите его как один always-блок с оператором `+`. Сравните временные диаграммы обеих версий: одинаков ли момент появления Carry относительно Sum и почему путь переноса и там, и там остаётся самым долгим.
Парная работа
Автор пишет модуль и проговаривает каждый порт: вход это или выход; ревьюер проверяет список портов против условия до компиляции и смотрит осциллограмму после теста, называя один сигнал, который меняется «между фронтами». Ревьюер не трогает мышь, но обязан спросить «какие порты у модуля?» до первой строки. Смена ролей — на каждом новом уровне блока.