Entender escalares y vectores en Verilog: Bits, registros y tipos de net
Verilog necesita representar bits individuales y grupos de bits. Por ejemplo, un elemento secuencial de un bit es un flip-flop. Pero uno de 16 bits es un registro que guarda 16 bits. Para esto, Verilog tiene escalares y vectores en nets y variables.
Escalar y Vector
Una declaración de net o reg sin especificación de rango se considera de 1 bit y es un escalar. Si se especifica un rango, se convierte en entidad multi-bit llamada vector.

wire o_nor; // net escalar de 1 bit
wire [7:0] o_flop; // net vector de 8 bits
reg parity; // variable escalar de 1 bit
reg [31:0] addr; // variable vector de 32 bits para guardar dirección
El rango permite direccionar bits individuales en un vector. El bit más significativo (MSB) debe especificarse como valor izquierdo en el rango y el menos significativo (LSB) a la derecha.
wire [msb:lsb] name;
integer my_msb;
wire [15:0] priority; // msb = 15, lsb = 0
wire [my_msb: 2] prior; // ilegal
Se crea un net de 16 bits llamado priority. MSB y LSB deben ser expresión constante, no variable. Pero pueden ser cualquier valor entero (positivo, negativo, cero) y LSB puede ser mayor, igual o menor que MSB.
Selección de bits (Bit-selects)
Cualquier bit en una variable vectorizada puede seleccionarse y asignarse individualmente. Esto se llama bit-select. Si el bit-select está fuera de límites o es x o z, el valor devuelto será x.

reg [7:0] addr; // variable reg de 8 bits [7,6,5,4,3,2,1,0]
addr[0] = 1; // asigna 1 al bit 0
addr[3] = 0; // asigna 0 al bit 3
addr[8] = 1; // ilegal: bit 8 no existe
Selección de partes (Part-selects)

Un rango de bits contiguos puede seleccionarse, llamado part-select. Hay dos tipos: part-select constante e indexado.
reg [31:0] addr;
addr[23:16] = 8'h23; // bits 23 a 16 reemplazados por 'h23 -> part-select constante
Un part-select variable permite usarse eficazmente en bucles para seleccionar partes del vector. Aunque el bit inicial puede variar, el ancho debe ser constante.
[<start_bit> +: <width>] // part-select incrementa desde start-bit
[<start_bit> -: <width>] // part-select decrementa desde start-bit
module des;
reg [31:0] data;
int i;
initial begin
data = 32'hFACE_CAFE;
for (i = 0; i < 4; i++) begin
$display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
end
$display ("data[7:0] = 0x%0h", data[7:0]);
$display ("data[15:8] = 0x%0h", data[15:8]);
$display ("data[23:16] = 0x%0h", data[23:16]);
$display ("data[31:24] = 0x%0h", data[31:24]);
end
endmodule
Salida de simulación:
ncsim> run data[8*0 +: 8] = 0xfe data[8*1 +: 8] = 0xca data[8*2 +: 8] = 0xce data[8*3 +: 8] = 0xfa data[7:0] = 0xfe data[15:8] = 0xca data[23:16] = 0xce data[31:24] = 0xfa ncsim: *W,RNQUIE: Simulation is complete.
Errores comunes
module tb;
reg [15:0] data;
initial begin
$display ("data[0:9] = 0x%0h", data[0:9]); // Error: orden inverso en part-select
end
endmodule
Verilog
- Dominar Verilog: Tutorial completo para diseño de circuitos digitales
- Dominar la concatenación en Verilog: Guía práctica
- Comprender las asignaciones en Verilog: tipos, sintaxis y mejores prácticas
- Bloqueante vs. No bloqueante en Verilog: Diferencias clave explicadas
- Dominar las funciones en Verilog para diseño RTL eficiente
- Comprender las Tasks en Verilog: Funciones vs Tasks, sintaxis y uso
- Comprender los retrasos inter e intra asignación en Verilog
- Generador de reloj en Verilog: Guía de diseño e implementación
- Dominar las funciones matemáticas en Verilog para diseño de hardware eficiente
- Dominar $timeformat en Verilog: Control de precisión y visualización
- Comprender e imprimir timescales de Verilog en cualquier alcance