Анатомия sized-литерала
У литерала Verilog до трёх частей:
8'b1010_1100
│ │ │
│ │ └─ цифры в выбранной базе
│ └─── base specifier: b (binary), h (hex), d (decimal), o (octal)
└────── ширина в битах (decimal)
Читаем слева направо: "8-битное значение, записанное в binary, цифры 10101100". Это 172 в decimal, 0xAC в hex - одни и те же биты, как ни запиши. Ширина говорит компилятору, сколько бит выделить; база говорит, как интерпретировать цифры.
Подчёркивания - визуальные разделители. 32'b1010_1100_0011_0101 - то же, что 32'b1010110000110101. Пользуйся ими.
Четыре базы
Hex (h) - стандарт для всего шире 4 бит. Binary (b) - стандарт, когда нужно читать битовые паттерны напрямую. Decimal (d) - для человекопонятных счётов. Octal (o) существует, но почти никогда не встретится.
Hex-цифры case-insensitive: 8'hAB и 8'hab идентичны.
Что происходит, когда значение не помещается?
Если цифр меньше, чем объявленная ширина, Verilog zero-extend'ит слева:
8'b101 // эквивалентно 8'b00000101 (= 5)
8'hF // эквивалентно 8'h0F (= 15)
Если цифр больше объявленной ширины, Verilog обрезает старшие с warning'ом:
4'hFF // обрезается до 4'hF, симулятор предупреждает
4'b10000 // обрезается до 4'b0000
Warning - твой друг. Не подавляй его.
Sized vs unsized
Литерал без ширины:
'd10 // unsized, дефолтный размер (≥32 бит)
10 // тоже unsized - без базы значит decimal
Unsized-литералы дефолтно 32 бита в большинстве тулов. Это источник целого класса багов:
reg [7:0] count;
if (count == -1) ... // -1 - unsized 32-битный; сравнение становится странным
Фикс - писать 8'hFF вместо -1, или 8'd255, или {8{1'b1}}. Всегда задавай ширину литералов, когда они используются в width-specific выражениях.
Единственное место, где unsized-литералы нормальны - счётчики integer в testbench-for-циклах, где integer достаточно широк, чтобы ничего удивительного не случилось.
Знаковые литералы
По умолчанию sized-литералы unsigned:
8'd255 // unsigned 255
8'b1111_1111 // unsigned 255 - тот же битовый паттерн, просто записан иначе
Если хочешь, чтобы литерал интерпретировался как знаковый - добавь s после апострофа:
8'sd10 // знаковое 10
8'sb1111_1111 // знаковое -1 (two's complement)
Флаг s важен для:
- Операторов
<<<и>>>(арифметические сдвиги) - они sign-extend'ят знаковые операнды. - Операторов сравнения на знаковых смешанных выражениях.
- Кастов
$signed/$unsigned.
Для большинства обычной арифметики на сигналах шин s оставляешь выключенным.
Числовые литералы с X и Z
Литеральная цифра может быть x (unknown) или z (high-impedance):
8'bx - shorthand для "все 8 бит unknown"; значение распространяется на объявленную ширину. Цифры x распространены в default-ветках state machines и в инициализации. Семантику разбираем в X and Z Values.
Где sized-литералы встречаются на практике
Как только начнёшь писать реальные модули, sized-литералы появляются везде:
// Ширины шин
input wire [31:0] addr;
wire [31:0] zero = 32'h0;
wire [31:0] all_ones = 32'hFFFF_FFFF;
// Кодировки состояний
localparam IDLE = 3'd0;
localparam BUSY = 3'd1;
localparam DONE = 3'd2;
// Маски
wire is_msb_set = data & 32'h8000_0000;
// Сравнения
if (counter == 8'd255) ...
// Reset-значения
always @(posedge clk) begin
if (reset) data_out <= 8'd0;
else data_out <= data_in;
end
Паттерн стабильный: пиши ширину, базу, цифры. У каждого литерала, к которому тянешься, одна и та же форма.
Тест-драйв
Теперь у тебя есть всё, чтобы написать любую константу, которая может понадобиться module на Verilog. Последний кусочек истории про типы данных - что происходит, когда сигнал не чистый 0 или 1: значения x и z.
Часто задаваемые вопросы
Что значит 8'b1010 в Verilog?
Это sized binary литерал: 8-битное значение, чьё двоичное представление - 00001010. Число до апострофа - ширина в битах; буква после апострофа - база (b binary, h hex, d decimal, o octal); цифры после - значение. Литерал zero-pad'ится слева, если цифр меньше, чем нужно для ширины.
В чём разница между sized и unsized числами в Verilog?
Sized литерал вроде 8'd10 ровно 8 бит шириной. Unsized литерал вроде 'd10 или просто 10 дефолтно 32 бита, что обычно слишком много. Смешивание unsized литералов с width-specific выражениями даёт тонкие баги - предпочитай sized везде, кроме одноразового тестового кода.
Как написать hex-число в Verilog?
Через base specifier 'h: 8'hFF - это 8-битное значение 255. Hex-цифры case-insensitive; 8'hff и 8'hFF идентичны. Цифры можно группировать подчёркиваниями для читаемости: 32'hDEAD_BEEF. Подчёркивания парсер игнорирует.
Как работают подчёркивания в числах Verilog?
Подчёркивания - это визуальные разделители, которые парсер игнорирует. 32'b1010_1100_0011_0101 - это ровно то же самое значение, что 32'b1010110000110101, но гораздо легче читается. Первый символ после префикса базы не может быть подчёркиванием, но в остальной строке цифр их можно ставить где угодно.
Как написать знаковое число в Verilog?
Добавь s после апострофа: 8'sd10 - знаковое 8-битное десятичное 10, 8'sb1111_1111 - знаковое -1. По умолчанию sized-литералы unsigned; модификатор s это переворачивает. Большая часть арифметики использует unsigned-операнды - тянись к signed только когда действительно нужно, чтобы отрицательные значения распространялись через <, >>> и подобные операторы.