Menu

Verilog Number Literals: Binário, Hex, Decimal e constantes com tamanho

Como o Verilog escreve constantes: sized vs unsized, as bases 'b 'h 'd 'o, números signed, underscores para legibilidade e as pegadinhas que mordem iniciantes.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

A anatomia de um literal sized

Um literal Verilog tem até três partes:

8'b1010_1100
│  │ │
│  │ └─ dígitos na base escolhida
│  └─── especificador de base: b (binário), h (hex), d (decimal), o (octal)
└────── largura em bits (decimal)

Lendo da esquerda para a direita: "um valor de 8 bits, escrito em binário, com os dígitos 10101100". Isso é 172 em decimal, 0xAC em hex, os mesmos bits independente de como você escreva. A largura diz ao compilador exatamente quantos bits alocar; a base diz como interpretar os dígitos.

Underscores são separadores visuais. 32'b1010_1100_0011_0101 é o mesmo que 32'b1010110000110101. Use-os.

As quatro bases

Hex (h) é o padrão para qualquer coisa mais larga que 4 bits. Binário (b) é o padrão quando você quer ler padrões de bit diretamente. Decimal (d) é para contagens com significado humano. Octal (o) existe mas você quase nunca verá.

Dígitos hex são case-insensitive: 8'hAB e 8'hab são idênticos.

O que acontece quando o valor não cabe?

Se seus dígitos não preencherem a largura declarada, Verilog zero-extende à esquerda:

8'b101       // equivalente a 8'b00000101  (= 5)
8'hF         // equivalente a 8'h0F        (= 15)

Se seus dígitos excedem a largura declarada, Verilog trunca os bits altos com um aviso:

4'hFF        // trunca para 4'hF, simulador avisa
4'b10000     // trunca para 4'b0000

O aviso é seu amigo. Não o suprima.

Sized vs Unsized

Um literal sem largura:

'd10    // unsized, pega o tamanho padrão (≥32 bits)
10      // também unsized - sem base significa decimal

Literais unsized por padrão são 32 bits na maioria das ferramentas. Essa é a fonte de uma classe inteira de bugs:

reg [7:0] count;
if (count == -1) ...      // -1 é unsized 32-bit; comparação fica estranha

A correção é escrever 8'hFF em vez de -1, ou 8'd255, ou {8{1'b1}}. Sempre dê tamanho a literais quando são usados em expressões específicas de largura.

O único lugar onde literais unsized estão bem é em contadores inteiros em loops for de testbench, onde o inteiro é largo o suficiente para nada surpreendente acontecer.

Literais signed

Por padrão, literais sized são unsigned:

8'd255   // unsigned 255
8'b1111_1111   // unsigned 255 - mesmo padrão de bit, apenas escrito diferente

Se você quer o literal interpretado como signed, adicione s depois do apóstrofo:

8'sd10           // signed 10
8'sb1111_1111    // signed -1 (complemento de dois)

A flag s importa para:

  • Os operadores <<< e >>> (shifts aritméticos) - eles fazem sign-extend de operandos signed.
  • Operadores de comparação em expressões mistas signed.
  • As conversões $signed/$unsigned.

Para a maioria da aritmética comum em sinais de barramento, você vai deixar o s de fora.

Literais numéricos com X e Z

Um dígito literal pode ser x (desconhecido) ou z (alta impedância):

8'bx é abreviação para "todos os 8 bits desconhecidos" - o valor é propagado para preencher a largura declarada. Dígitos x são comuns em casos default de máquinas de estado e em inicialização. Cobrimos a semântica em X e Z Values.

Onde literais sized aparecem na prática

Uma vez que você começa a escrever modules reais, literais sized aparecem em todos os lugares:

// Larguras de barramento
input  wire [31:0] addr;
wire [31:0] zero = 32'h0;
wire [31:0] all_ones = 32'hFFFF_FFFF;

// Codificações de estado
localparam IDLE = 3'd0;
localparam BUSY = 3'd1;
localparam DONE = 3'd2;

// Máscaras
wire is_msb_set = data & 32'h8000_0000;

// Comparações
if (counter == 8'd255) ...

// Valores de reset
always @(posedge clk) begin
    if (reset) data_out <= 8'd0;
    else       data_out <= data_in;
end

O padrão é consistente: escreva a largura, escreva a base, escreva os dígitos. Cada literal que você usa tem a mesma forma.

Um test drive

Você agora tem tudo que precisa para escrever qualquer constante que um module Verilog poderia querer. A última peça da história de tipos de dado é o que acontece quando um sinal não é um 0 ou 1 limpo - os valores x e z.

Perguntas frequentes

O que 8'b1010 significa em Verilog?

É um literal binário com tamanho: um valor de 8 bits cuja representação binária é 00001010. O número antes do apóstrofo é a largura em bits; a letra depois do apóstrofo é a base (b binário, h hex, d decimal, o octal); os dígitos depois são o valor. O literal é preenchido com zeros à esquerda se os dígitos não preencherem a largura.

Qual a diferença entre números sized e unsized em Verilog?

Um literal sized como 8'd10 tem exatamente 8 bits de largura. Um literal unsized como 'd10 ou simplesmente 10 por padrão é 32 bits, o que geralmente é demais. Misturar literais unsized em expressões específicas de largura causa bugs sutis - prefira literais sized em todos os lugares fora de código de teste descartável.

Como escrevo um número hex em Verilog?

Use o especificador de base 'h: 8'hFF é um valor de 8 bits igual a 255. Dígitos hex são case-insensitive; 8'hff e 8'hFF são idênticos. Você pode agrupar dígitos com underscores para legibilidade: 32'hDEAD_BEEF. Os underscores são ignorados pelo parser.

Como underscores funcionam em números Verilog?

Underscores são separadores visuais que o parser ignora. 32'b1010_1100_0011_0101 é exatamente o mesmo valor que 32'b1010110000110101 mas muito mais fácil de ler. O primeiro caractere depois do prefixo de base não pode ser um underscore, mas você pode colocá-los em qualquer outro lugar na string de dígitos.

Como escrevo um número signed em Verilog?

Adicione s depois do apóstrofo: 8'sd10 é um decimal signed 10 de 8 bits, e 8'sb1111_1111 é signed -1. Por padrão, literais sized são unsigned; o modificador s inverte isso. A maioria da aritmética usa operandos unsigned - recorra a signed só quando você genuinamente precisa que valores negativos se propaguem por <, >>> e operadores similares.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR