Menu
CoddyTech

Блок Always

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

Процедурный блок — это блок кода, в котором инструкции выполняются одна за другой, последовательно, как и в языках программирования, например C или Python. В Verilog есть два процедурных блока: initial (выполняется один раз) и always (выполняется непрерывно). Начнём с блока always.

Блок always выполняется непрерывно. После начала симуляции он повторяется бесконечно. Его используют для описания аппаратных компонентов, которые должны продолжать работать, например триггеров, счётчиков и комбинационной логики.

Базовый синтаксис:

always @(sensitivity_list) begin
  // Код, который выполняется многократно
end

@(sensitivity_list) указывает блоку, когда выполняться. Без него (и без задержки, например #5 внутри блока) блок бесконечно зациклился бы и остановил симуляцию.

Пример блока always: счётчик

Вот пример того, как мы можем использовать блок always для создания счётчика.

module counter (
  input clk,
  output reg [3:0] count
);
  always @(posedge clk) count <= count + 1;
endmodule

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

ЧастьЗначение
alwaysВыполнять этот код снова и снова, бесконечно
@(posedge clk)Дождаться, когда тактовый сигнал изменится с 0 на 1 (положительный фронт)
count <= count + 1Взять текущее значение count, прибавить 1 и сохранить его обратно

Блок выполняется при каждом нарастающем фронте тактового сигнала. Каждый раз count увеличивается на 1.

Список чувствительности @(posedge clk) указывает выполнять его только по фронтам тактового сигнала, а не непрерывно. Без этого цикл выполнялся бы бесконечно без задержки.

Блок always с несколькими сигналами

Можно перечислить конкретные сигналы:

always @(a or b) begin
  out = a & b;
end

Это выполняется, когда изменяется a или b.

challenge icon

Задание

Добавь отсутствующий блок always, чтобы этот модуль работал.

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

  • На каждом положительном фронте тактового сигнала значение out1 переключается с 0 на 1 или с 1 на 0
  • Значение out2 следует за out1 (совпадает со значением out1)

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

  1. Добавь блок always @(posedge clk)
  2. Внутри переключай значение out1 (используй out1 = ~out1)
  3. Присвой out2 значение out1

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

module toggler (
  input clk,
  output reg out1,
  output reg out2
);

  initial begin
    out1 = 0;
    out2 = 0;
  end

  // TODO: Добавить блок always с posedge clk
  // out1 переключается при каждом тактовом импульсе
  // out2 повторяет out1

endmodule
quiz iconПроверьте себя

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор Verilog