Блоки "Always"
Как предполагает само название, блок “always” выполняется всегда, в то время как блок “initial” выполняется лишь один раз (в начале симуляции). Вторым различием является тот факт, что блок “always” должен содержать список чувствительности или задержку, связанную с ним.
Список чувствительности говорит блоку “always”, когда выполнять блок кода, как показано на рисунке ниже. Символ @ после зарезервированного слова “always” отображает тот факт, что блок будет применен в случае условия вставки скобок после символа @. Важное примечание касательно блока “always”: он не может работать с типом данных wire, но работает с типами данных reg и integer.
Verilog Code:
always @ (a or b or sel) begin y = 0; if (sel == 0) begin y = a; end else begin y = b; 8 end 9 end
Пример выше представляет собой мультиплексор 2:1 со входными параметрами a и b; sel – сигнал выбора, а у – выход мультиплексора. При любой комбинационной логике, выходной параметр меняется тогда, когда меняется входной параметр. Эта теория при применении к блокам “always” означает тот факт, что код внутри блоков “always” должен выполняться каждый раз, когда меняются переменные на входе (либо управляющие переменные на выходе). Эти переменные включены в список чувствительности под названием a, b и sel. Существует два типа списка чувствительности: чувствительный к уровню (для комбинационных цепей) и чувствительный к фронту (для триггеров). Код ниже представляет собой все тот же мультиплексор 2:1, но выходной параметр у уже выступает в качестве выхода триггера.
Verilog Code:
always @ (posedge clk ) if (reset == 0) begin y <= 0; end else if (sel == 0) begin y <= a; end else begin y <= b; end
При нормальных условиях мы должны возвращать триггеры в исходное положение, следовательно, каждый раз, когда счетчик делает переход от 0 на 1 (posedge), мы проверяем инициацию сброса (синхронный сброс). Затем, продолжаем работу с обычной логикой. Если посмотреть внимательнее, то можно увидеть, что в случае комбинационной логики мы имеем "=" для присвоения, а для последовательного блока мы имеем оператор "<=".
Таким образом, "=" представляет собой блокирующее присваивание, а "<=" – неблокирующее присваивание. "=" выполняет код последовательно внутри цикла begin / end, в то время как неблокирующее "<=" выполняет код параллельно. Мы можем иметь блок “always” без списка чувствительности, но в этом случае нам потребуется задержка, как показано в коде ниже.
Verilog Code:
always begin #5 clk = ~clk; end
#5 перед предложением задерживает его выполнение на 5 единиц времени.
Присваивание состояния
Присваивание состояния используется для моделирования только комбинационной логики, и выполняется непрерывно. Таким образом, присваивание состояния называется “непрерывным присваиванием состояния”, так как отсутствует список чувствительности.
Verilog Code:
assign out = (enable) ? data : 1'bz;
Приведенный выше пример представляет собой буферный элемент с тремя состояниями. При 1, данные выводятся на выход, в противном случае выход переходит в состояние высокого импеданса. Мы можем иметь вложенные условные операторы для сборки мультиплексоров, дешифраторов и шифраторов.
Verilog Code:
assign out = data;
Настоящий пример представляет собой простой буферный элемент.
Задачи и функции
При повторении аналогичных старых операций вновь и вновь, язык Verilog, как и любой другой язык программирования, предоставляет средства для вызова повторенного кода, это и называется “Задачи и Функции”. Хотелось бы иметь что-то похожее для веб-страниц, просто для вывода содержимого этого языка программирования вновь и вновь. Приведенный ниже код используется для проверки на четность.
Verilog Code:
function parity; input [31:0] data; integer i; begin parity = 0; for (i= 0; i < 32; i = i + 1) begin parity = parity ^ data[i]; end end endfunction
Функции и задачи имеют один и тот же синтаксис; единственным различием является тот факт, что задачи могут иметь задержки, в то время как функции не могут иметь каких-либо задержек. Это означает, что функция может использоваться для моделирования комбинационной логики. Вторым различием является возврат значения функциями, чего не могут сделать задачи.