Menu
Coddy logo textTech

Неблокирующее присваивание

Часть раздела Основы путешествия по Verilog на Coddy — урок 50 из 90.

В предыдущем уроке мы рассмотрели блокирующее присваивание (=), которое выполняется последовательно. Теперь мы рассмотрим неблокирующее присваивание (<=), которое выполняется одновременно — параллельно.

Неблокирующее присваивание использует оператор <=. Оно называется «неблокирующим», потому что оно не блокирует выполнение следующего оператора. Все неблокирующие присваивания в блоке выполняются одновременно.

Синтаксис:

variable <= expression;

Когда использовать неблокирующее присваивание

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

Примеры последовательностной логики:

  • Триггеры
  • Регистры
  • Счетчики
  • Конечные автоматы
  • Сдвиговые регистры

Пример на Verilog:

initial begin
  a <= 5;      // Запланировано, но еще не выполнено
  b <= a + 2;  // Запланировано, используется СТАРОЕ значение a
  c <= b * 3;  // Запланировано, используется СТАРОЕ значение b
end

Все три присваивания происходят одновременно с использованием старых значений. В конце временного шага все обновления происходят вместе.

Неблокирующие присваивания в блоках Always (последовательная логика)

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

always @(posedge clk) begin
  q <= d;           // q принимает значение d по фронту тактового сигнала
  count <= count + 1; // count увеличивается по фронту тактового сигнала
end

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

Итог

ПравилоОбъяснение
Используйте <= для последовательной логикиalways @(posedge clk)
Используйте = для комбинационной логикиalways @(*)
Неблокирующее присваивание выполняется параллельноВсе присваивания происходят одновременно
Значения обновляются в конце временного шагаНе сразу
challenge icon

Задание

Завершите неблокирующее присваивание

Добавьте недостающие неблокирующие присваивания, чтобы этот 2-битный сдвиговый регистр заработал.

Как это работает:

  • На каждом фронте тактового сигнала q1 получает d
  • q2 получает старое значение q1

Что нужно сделать:

  1. Присвойте d переменной q1 (неблокирующее присваивание)
  2. Присвойте q1 переменной q2 (неблокирующее присваивание)

Шпаргалка

Неблокирующее присваивание (<=) выполняет все инструкции параллельно — используя старые значения и обновляя их в конце временного шага.

// Все используют СТАРЫЕ значения a и b
a <= 5;
b <= a + 2;  // использует старое a
c <= b * 3;  // использует старое b

Используйте <= для последовательной логики (триггеры, регистры, счетчики) внутри тактируемых блоков always:

always @(posedge clk) begin
  q     <= d;           // неблокирующее
  count <= count + 1;   // неблокирующее
end
ПрисваиваниеПрименениеВыполнение
<=Последовательная логика (posedge clk)Параллельно
=Комбинационная логика (always @(*))Пошагово

Попробуйте сами

module shift_register (
  input clk,
  input reset,
  input d,
  output reg q1,
  output reg q2
);
  
  always @(posedge clk or posedge reset) begin
    if (reset) begin
      q1 <= 0;
      q2 <= 0;
    end else begin
      // TODO: Добавить логику сдвига
      // Шаг 1: Присвоить d в q1 (неблокирующее присваивание)
      // Шаг 2: Присвоить q1 в q2 (неблокирующее присваивание)
    end
  end
endmodule
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Основы