Комбинационная логика: assign и оператор «всё сразу»

Учимся описывать логику без памяти, которая пересчитывается мгновенно при любом изменении входов.

Комбинационная логика — схема, выход которой зависит только от текущих значений входов (без памяти о прошлом); результат пересчитывается «сразу», как только меняется любой вход.

Всю цифровую логику делят на два класса: комбинационную (без памяти) и последовательностную (с памятью, тактируемую). Начнём с комбинационной — она проще и нагляднее всего показывает параллельную природу железа. Комбинационная схема — это чистая функция от входов: подали входы — мгновенно получили выход, никакой истории.

Непрерывное присваивание assign

Главный инструмент комбинационной логики — assign. Он создаёт непрерывную связь: левая часть всегда равна правой. Это не «вычислить один раз», а «провести провод, по которому значение течёт постоянно». Как только меняется любой вход справа, выход слева пересчитывается мгновенно (с точностью до физической задержки вентилей).

assign y = a & b;          // y всегда равно a AND b
assign z = (a | b) & ~c;   // z пересчитывается при изменении a, b или c
assign w = sel ? x : y;    // условный оператор: мультиплексор (см. след. урок)

Несколько assign в модуле работают параллельно и независимо — это разные куски железа. Порядок их записи не имеет значения.

Операторы Verilog

Важно различать два семейства операторов:

Битовые (поразрядно над шинами)Логические (дают 1 бит: истина/ложь)
& И, | ИЛИ, ^ XOR, ~ НЕ&& И, || ИЛИ, ! НЕ

Битовый & применяется к каждой паре битов шин (8'b1100 & 8'b1010 = 8'b1000), а логический && сводит операнды к «истина/ложь» и даёт один бит. Есть ещё операторы сравнения (==, !=, <, >), арифметические (+, -, *) и сдвиги (<< влево, >> вправо). Все они в комбинационном контексте описывают соответствующее железо: сравнение — компаратор, сложение — сумматор, сдвиг — переразводку проводов.

Как работает под капотом: всё происходит «сразу»

Ключевая интуиция: комбинационная схема не «выполняет шаги», она просто есть. Подайте на входы значения — и через крошечную задержку (пока сигнал пробежит по вентилям) на выходе появится результат. Промоделируем комбинационный модуль — побитовые операции над двумя 4-битными шинами — на Python, чтобы увидеть, что выходы зависят только от входов:

# Комбинационный блок: по входам a,b мгновенно считаем три выхода
def comb(a, b):
    and_out = a & b            # побитовое И
    or_out  = a | b            # побитовое ИЛИ
    xor_out = a ^ b            # побитовое XOR
    return and_out, or_out, xor_out

for a, b in [(0b1100, 0b1010), (0b1111, 0b0001), (0b0000, 0b1111)]:
    aa, oo, xx = comb(a, b)
    print(f"a={a:04b} b={b:04b} | AND={aa:04b} OR={oo:04b} XOR={xx:04b}")

Вывод:

a=1100 b=1010 | AND=1000 OR=1110 XOR=0110
a=1111 b=0001 | AND=0001 OR=1111 XOR=1110
a=0000 b=1111 | AND=0000 OR=1111 XOR=1111

Никакого состояния: подали те же входы — получили тот же выход, всегда. Это и значит «без памяти». В железе три выхода считаются одновременно тремя группами вентилей.

Частые ошибки

  • Путать & и &&. Для поразрядных операций над шинами нужен битовый &; логический && схлопнет шину в один бит.
  • Ждать «выполнения» assign по порядку. Все assign активны постоянно и параллельно; порядок строк роли не играет.
  • Создавать комбинационную петлю. Если assign a = b; и assign b = a; зависят друг от друга без триггера, получится логический цикл — схема «зациклится» и станет нестабильной.

Итог

  • Комбинационная логика — функция от входов без памяти; результат «сразу».
  • assign создаёт постоянную связь «выход всегда равен выражению».
  • Различайте битовые (&, |, ^) и логические (&&, ||) операторы.
  • Избегайте комбинационных петель — они делают схему нестабильной.
Проверьте себя
1. Что описывает непрерывное присваивание assign в Verilog?
AОднократное вычисление при старте
BПостоянную связь: левая часть всегда равна правой и пересчитывается при изменении входов
CЗапись значения в память по такту
DОбъявление переменной
2. Чем битовый оператор & отличается от логического &&?
AОни полностью эквивалентны
B& работает поразрядно над всеми битами шины, а && сводит операнды к одному биту истина/ложь
C& работает только с числами, && только со строками
D&& быстрее в железе
3. Почему комбинационную логику называют логикой «без памяти»?
AОна не использует ресурсы FPGA
BЕё выход зависит только от текущих входов, а не от прошлых значений
CОна не может вычислять сложные функции
DОна работает только один раз