One hexadecimal digit is exactly four bits (a nibble). Split binary into groups of four from the right, then translate each group.
Hex | Binary | Dec | Hex | Binary | Dec |
|---|---|---|---|---|---|
0 | 0000 | 0 | 8 | 1000 | 8 |
1 | 0001 | 1 | 9 | 1001 | 9 |
2 | 0010 | 2 | A | 1010 | 10 |
3 | 0011 | 3 | B | 1011 | 11 |
4 | 0100 | 4 | C | 1100 | 12 |
5 | 0101 | 5 | D | 1101 | 13 |
6 | 0110 | 6 | E | 1110 | 14 |
7 | 0111 | 7 | F | 1111 | 15 |
Example: 1011_0110_1100 regroups as B 6 C, so it is 12'hB6C. Going the other way, 16'hA5F0 expands to 1010_0101_1111_0000.
Four habits save time:
Memorize powers of two up to 2¹⁶ (65,536). Sizes of memories and buses come straight from them.
A hex digit of F is all ones; 8 is a lone top bit; 5 and A alternate (0101 / 1010), handy for test patterns.
To get a decimal value, convert hex nibble by nibble: 8'h3C = 3·16 + 12 = 60.
Memory addresses: 1 KiB = 2¹⁰ = 0x400, 4 KiB = 0x1000, 64 KiB = 0x1_0000.
A sized literal has the form <size>'[s]<base><digits>; the optional s marks a signed value. In 8'sd16, 8 is the width, ' starts the base notation, s means signed, d means decimal and 16 is the value. It stores 0001_0000. In 8'shF0, the same width and signed marker make 1111_0000 mean -16. Write a negative decimal value with a separate unary minus, for example -8'sd16. Underscores are ignored and improve readability.
Read the top row left to right as the literal is written; the bottom row is what the simulator stores.
Size first: 8 fixes the width before any digit is read, so F0 fills exactly bits 7 to 0.
The s changes meaning, not bits: the stored pattern is 1111_0000 either way; s makes the top bit a sign bit, so the value is -16 instead of 240.
Each hex digit is one nibble: F covers bits 7 to 4 and 0 covers bits 3 to 0.
Literal | Meaning | Width |
|---|---|---|
| binary 1010 | 4 bits |
| hex FF | 8 bits |
| decimal 100 | 12 bits |
| signed decimal +16 | 8 bits |
| signed bit pattern for -16 | 8 bits |
| too many digits for 16 bits: truncated | 16 bits |
| decimal 10, size omitted | 32 bits |
| contains unknown bits | 8 bits |
module tb_literals;
logic [3:0] n = 4'hA;
int errors = 0;
initial begin
if (n !== 4'b1010) errors++;
if (8'h3C !== 8'd60) errors++;
if (12'b1011_0110_1100 !== 12'hB6C) errors++;
if ($bits('d10) !== 32) errors++; // unsized decimal is 32 bits
if ($bits(4'd10) !== 4) errors++;
if (errors == 0) $display("PASS: literal widths and values as described");
$finish;
end
endmodulereg [15:0] r = 'hFF; use for the literal, and does r end up as 16'h00FF?The literal itself is 32 bits wide (unsized). Assigned to a 16-bit register it is truncated to the low 16 bits, giving 16'h00FF. It works here, but the same habit with a larger value silently discards bits.