Шпаргалка по Verilog
Последнее обновление
Структура модуля и порты
Модуль - базовый строительный блок: у него есть имя и список портов.
| Синтаксис | Значение |
|---|---|
module adder(...); ... endmodule | Объявить модуль и его тело |
input clk; | Входной порт |
output q; | Выходной порт |
output reg q; | Выход, управляемый из блока always |
input [7:0] data; | 8-битная входная шина (вектор) |
inout sda; | Двунаправленный порт |
adder u1 (.a(x), .b(y), .sum(s)); | Инстанцировать модуль через именованные порты |
Типы данных
wire моделирует соединение; reg хранит значение, присваиваемое процедурным кодом.
| Элемент | Что делает |
|---|---|
wire w; | Цепь, управляемая assign или выходом модуля |
reg r; | Хранит значение, присвоенное внутри блока always/initial |
wire [3:0] bus; | 4-битный вектор (биты с 3 по 0) |
reg [7:0] count; | 8-битный регистр |
bus[2] | Выбрать один бит |
bus[3:1] | Выбрать срез битов (частичная выборка) |
reg mem [0:255]; | Память: массив регистров |
parameter WIDTH = 8; | Именованная константа модуля |
Числовые литералы
Формат - <size>'<base><value>: размер в битах, основание как b/o/d/h.
| Синтаксис | Значение |
|---|---|
4'b1010 | 4-битное двоичное, значение 10 |
8'hFF | 8-битное шестнадцатеричное, значение 255 |
8'hff | То же - hex-цифры нечувствительны к регистру |
16'd255 | 16-битное десятичное, значение 255 |
3'o7 | 3-битное восьмеричное, значение 7 |
8'b1010_1100 | Подчёркивания группируют цифры для читаемости |
1'bx | Неизвестное (x) значение бита |
1'bz | Высокоимпедансное (z) значение бита |
Операторы
Битовые, логические, операторы сравнения и редукции.
| Оператор | Что делает |
|---|---|
& | ^ ~ | Битовые AND, OR, XOR, NOT |
&& || ! | Логические AND, OR, NOT (возвращают 1 бит) |
== != < > <= >= | Операторы сравнения |
<< >> | Сдвиг влево и вправо |
+ - * / % | Арифметические операторы |
&bus | Редукция AND (AND всех битов) |
|bus | Редукция OR (OR всех битов) |
^bus | Редукция XOR (чётность всех битов) |
{a, b} | Конкатенация; {4{1'b1}} повторяет до 4'b1111 |
Непрерывное присваивание
assign непрерывно управляет проводом - используйте для комбинационной логики.
| Синтаксис | Значение |
|---|---|
assign y = a & b; | Управлять y результатом AND a и b |
assign sum = a + b; | Непрерывно вычислять сумму |
assign y = sel ? a : b; | Тернарный оператор - мультиплексор 2 в 1 |
assign {c, s} = a + b; | Захватить перенос и сумму вместе |
assign y = ~en; | Управлять проводом от инвертированного сигнала |
Процедурные блоки
always и initial выполняют операторы; список чувствительности задаёт, когда.
| Синтаксис | Значение |
|---|---|
always @(*) begin ... end | Комбинационная логика (при любом изменении входа) |
always @(posedge clk) | Выполнять по каждому фронту тактового сигнала (последовательная) |
always @(negedge clk) | Выполнять по каждому спаду тактового сигнала |
always @(posedge clk or posedge rst) | Тактируемый блок с асинхронным сбросом |
initial begin ... end | Выполнить один раз в момент 0 (тестбенчи, только симуляция) |
begin ... end | Сгруппировать несколько операторов |
#10 | Задержка на 10 единиц времени (только симуляция) |
Блокирующее против неблокирующего
Используйте = для комбинационной логики, <= для тактируемой последовательной логики.
| Синтаксис | Значение |
|---|---|
a = b; | Блокирующее - выполняется по порядку, немедленно |
a <= b; | Неблокирующее - сначала читаются все правые части, потом присваивается |
always @(*) y = a & b; | Комбинационная: используйте блокирующее = |
always @(posedge clk) q <= d; | Триггер: используйте неблокирующее <= |
Смешивание = и <= в одном блоке | Избегайте этого - частый источник ошибок |
Управление потоком
Условия и многовариантные ветвления внутри процедурных блоков.
| Синтаксис | Значение |
|---|---|
if (cond) ... else ... | Условный оператор |
if (a) x = 1; else x = 0; | Однострочный if/else |
case (sel) ... endcase | Многовариантное ветвление по значению |
2'b00: y = a; | Пункт case |
default: y = 0; | Запасной пункт case |
for (i = 0; i < 8; i = i + 1) | Цикл (часто внутри generate или симуляции) |
repeat (4) @(posedge clk); | Повторить оператор N раз |
Частые паттерны
Строительные блоки, которые вы пишете снова и снова, плюс задачи тестбенча.
| Паттерн | Синтаксис |
|---|---|
| D-триггер | always @(posedge clk) q <= d; |
| Регистр со сбросом | always @(posedge clk) if (rst) q <= 0; else q <= d; |
| Счётчик | always @(posedge clk) count <= count + 1; |
| Регистр состояния FSM | always @(posedge clk) state <= next_state; |
| Логика следующего состояния FSM | always @(*) case (state) ... endcase |
| Вывести значение | $display("q = %b", q); |
| Вывод при изменении | $monitor("t=%0t q=%b", $time, q); |
| Завершить симуляцию | $finish; |
Каждый элемент синтаксиса Verilog, который вам нужен, на одной странице. Эта шпаргалка по Verilog - быстрый справочник по языку описания аппаратуры: объявление модулей и портов, выбор типов данных, написание комбинационной и последовательной логики, а также паттерны блоков always, описывающие реальные схемы.
Здесь приведён стандартный синтаксис Verilog (IEEE 1364), работающий в распространённых симуляторах вроде Icarus Verilog и Verilator. Копируйте нужное или попробуйте его вживую в playground для Verilog - напишите модуль, смоделируйте его и увидите вывод в браузере.
Часто задаваемые вопросы по шпаргалке Verilog
Эта шпаргалка по Verilog бесплатна?
В чём разница между wire и reg?
wire моделирует физическое соединение и должен управляться непрерывно - оператором assign или выходом модуля - поэтому его используют для комбинационных цепей. reg хранит своё значение, пока процедурный код его не изменит, поэтому его используют для всего, что присваивается внутри блока always или initial. Несмотря на название, reg не всегда становится аппаратным регистром; это лишь означает, что значение задаётся процедурно.В чём разница между блокирующим и неблокирующим присваиванием?
=) выполняется немедленно и по порядку, как обычный оператор программирования, поэтому используйте его для комбинационной логики в блоках always @(*). Неблокирующее присваивание (<=) сначала вычисляет все правые части, а затем обновляет левые части одновременно, что корректно моделирует триггеры - поэтому используйте его в тактируемых блоках always @(posedge clk). Смешивание этих двух в одном блоке - классический источник ошибок симуляции.