Menu

Operadores bit a bit y de reducción en Verilog

Los operadores a nivel de bit en Verilog: AND/OR/XOR bit a bit, las formas de inversión y los operadores de reducción que colapsan un vector entero a un solo bit.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Dos roles para el mismo símbolo

&, |, ^ y sus hermanos invertidos aparecen en dos formas distintas:

  • Forma binaria (dos operandos): a & b - operación bit a bit entre vectores del mismo ancho.
  • Forma unaria (un operando): &a - reducción de todos los bits de a a un solo bit.

El compilador los distingue contando los operandos. La convención de nombres que usa la gente es "los operadores bit a bit" para la forma binaria y "los operadores de reducción" para la forma unaria.

Bit a bit: un bit cada vez

El conjunto completo:

OperadorNombreBit de salida en la posición N
a & bANDa[N] AND b[N]
a | bORa[N] OR b[N]
a ^ bXORa[N] XOR b[N]
a ~& bNANDNOT (a[N] AND b[N])
a ~| bNORNOT (a[N] OR b[N])
a ~^ bXNORNOT (a[N] XOR b[N])
~aNOTNOT a[N]

Ten en cuenta que ~&, ~|, ~^ se escriben con la tilde primero y el operador después. Son un único token; no hay espacio en medio.

Cuando los dos operandos tienen anchos distintos, el más estrecho se extiende con ceros a la izquierda para igualar. Si quieres extensión de signo, usa operandos con signo explícitamente con $signed().

Reducción: de muchos bits a uno

Las formas unarias de los mismos operadores colapsan un vector a un solo bit:

Qué significa cada uno:

  • &data devuelve 1 si todos los bits de data son 1, si no 0. Útil para chequeos del tipo "¿es todo unos?".
  • |data devuelve 1 si cualquier bit de data es 1, si no 0. Útil para chequeos del tipo "¿es distinto de cero?".
  • ^data devuelve la paridad - XOR de todos los bits. 1 si hay un número impar de unos, 0 si es par.
  • ~&data, ~|data, ~^data son los inversos de los anteriores.

Los verás por todas partes en código real:

wire empty       = ~|fifo_count;       // empty solo si count es cero
wire all_ones    = &mask;              // todos los bits a 1
wire parity_bit  = ^data;              // paridad de un byte
wire any_request = |request_vector;    // ¿hay algo solicitado?

Las formas de reducción son concisas y sintetizan a árboles de puertas obvios: & se reduce a una puerta AND de varias entradas, | a un OR de varias entradas, ^ a un árbol XOR (que es también el generador de paridad en hardware).

Patrones comunes

Poner y limpiar bits

wire [7:0] data;
wire [7:0] mask = 8'b0000_1000;

wire [7:0] set     = data | mask;     // fuerza el bit 3 a 1
wire [7:0] cleared = data & ~mask;    // fuerza el bit 3 a 0
wire [7:0] toggled = data ^ mask;     // invierte el bit 3
wire [7:0] tested  = data & mask;     // cero si el bit 3 era 0, distinto de cero si no

Estos son los mismos modismos de manipulación de bits que usarías en C. Sintetizan a operaciones de una sola puerta.

Comprobar si un valor es igual a todo unos

wire is_max = &counter;       // 1 si cada bit de counter es 1

Un AND de reducción con una puerta, frente a escribir counter == 8'hFF (que también funcionaría; los sintetizadores normalmente producen hardware idéntico).

Generar un bit de paridad

Detectar cualquier señal activa

wire any_pending = |request_vector;

Si request_vector es ancho (digamos 64 solicitantes), el OR de reducción colapsa a una única señal que puedes meter en un codificador de prioridad o un árbitro.

Operadores de desplazamiento

Ya que estamos con operadores a nivel de bit, los desplazamientos:

  • a << N desplaza a N posiciones a la izquierda, rellenando con ceros por la derecha.
  • a >> N desplaza a N posiciones a la derecha, rellenando con ceros por la izquierda.
  • a <<< N desplazamiento aritmético a la izquierda (igual que << para sin signo).
  • a >>> N desplazamiento aritmético a la derecha - rellena con el bit de signo cuando a tiene signo.

Los desplazamientos por una constante son gratis en hardware (solo recableado). Los desplazamientos por una variable en runtime producen un barrel shifter, que es más grande pero sigue siendo barato.

Qué viene a continuación

Ya has visto cada operador que devuelve un único valor. El siguiente doc - Concatenation and Replication - cubre la sintaxis {} y {N{...}} que construye vectores más anchos a partir de piezas, que usarás constantemente cuando conectes módulos de diferentes anchos.

Preguntas frecuentes

¿Qué son los operadores bit a bit en Verilog?

Los operadores bit a bit combinan dos vectores del mismo ancho posición por posición. a & b aplica AND al bit 0 de a con el bit 0 de b, al bit 1 con el bit 1, y así sucesivamente, produciendo un vector del mismo ancho que las entradas. El conjunto completo es & (AND), | (OR), ^ (XOR), ~ (NOT), y las formas de inversión ~&, ~|, ~^ (NAND, NOR, XNOR).

¿Qué es un operador de reducción en Verilog?

Un operador de reducción es una forma unaria de un operador bit a bit que colapsa un vector entero a un solo bit. &data devuelve 1 solo si todos los bits de data son 1. |data devuelve 1 si cualquier bit es 1. ^data devuelve el XOR de todos los bits - la paridad. Las formas de reducción no tienen operando a la izquierda, solo a la derecha.

¿Cuál es la diferencia entre & y && en Verilog?

& es AND bit a bit - empareja bits posición por posición y el resultado tiene el mismo ancho que los operandos. && es AND lógico - trata cada operando como un booleano (cero vs distinto de cero) y devuelve un resultado de 1 bit. 4'b1100 & 4'b0011 es 4'b0000; 4'b1100 && 4'b0011 es 1.

¿Cómo se calcula la paridad en Verilog?

Usa el operador XOR de reducción: parity = ^data. Aplica XOR a todos los bits de data. Para un vector de 8 bits eso es data[7] ^ data[6] ^ ... ^ data[0]. El resultado es 1 si hay un número impar de bits a 1, 0 si es par. Invertir con ~^ da paridad par.

¿Qué hace ~ en Verilog?

~ es NOT bit a bit - invierte cada bit de su operando. ~4'b1100 es 4'b0011. No lo confundas con ! (NOT lógico), que colapsa el operando a un booleano de un bit y lo invierte. !4'b1100 es 1'b0 (el operando es distinto de cero, NOT-ing del valor de verdad da 0).

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR