Hoja de Trucos de Verilog
Última actualización
Estructura de módulos y puertos
Un módulo es el componente básico: tiene un nombre y una lista de puertos.
| Sintaxis | Significado |
|---|---|
module adder(...); ... endmodule | Define un módulo y su cuerpo |
input clk; | Un puerto de entrada |
output q; | Un puerto de salida |
output reg q; | Una salida controlada desde un bloque always |
input [7:0] data; | Un bus de entrada de 8 bits (vector) |
inout sda; | Un puerto bidireccional |
adder u1 (.a(x), .b(y), .sum(s)); | Instancia un módulo por puertos con nombre |
Tipos de datos
wire modela una conexión; reg contiene un valor que asigna el código procedural.
| Elemento | Qué hace |
|---|---|
wire w; | Una red controlada por assign o por la salida de un módulo |
reg r; | Contiene un valor asignado dentro de un bloque always/initial |
wire [3:0] bus; | Un vector de 4 bits (bits del 3 al 0) |
reg [7:0] count; | Un registro de 8 bits |
bus[2] | Selecciona un solo bit |
bus[3:1] | Selecciona un segmento de bits (part-select) |
reg mem [0:255]; | Una memoria: un array de registros |
parameter WIDTH = 8; | Una constante con nombre para el módulo |
Literales numéricos
El formato es <size>'<base><value>: tamaño en bits, base como b/o/d/h.
| Sintaxis | Significado |
|---|---|
4'b1010 | Binario de 4 bits, valor 10 |
8'hFF | Hexadecimal de 8 bits, valor 255 |
8'hff | Igual: los dígitos hexadecimales no distinguen mayúsculas |
16'd255 | Decimal de 16 bits, valor 255 |
3'o7 | Octal de 3 bits, valor 7 |
8'b1010_1100 | Los guiones bajos agrupan dígitos para mejorar la legibilidad |
1'bx | Un valor de bit desconocido (x) |
1'bz | Un valor de bit de alta impedancia (z) |
Operadores
Operadores a nivel de bits, lógicos, de comparación y de reducción.
| Operador | Qué hace |
|---|---|
& | ^ ~ | AND, OR, XOR, NOT a nivel de bits |
&& || ! | AND, OR, NOT lógicos (devuelven 1 bit) |
== != < > <= >= | Operadores de comparación |
<< >> | Desplazamiento a la izquierda y a la derecha |
+ - * / % | Operadores aritméticos |
&bus | Reducción AND (AND de todos los bits) |
|bus | Reducción OR (OR de todos los bits) |
^bus | Reducción XOR (paridad de todos los bits) |
{a, b} | Concatenación; {4{1'b1}} se replica a 4'b1111 |
Asignación continua
assign controla un wire de forma continua: úsalo para lógica combinacional.
| Sintaxis | Significado |
|---|---|
assign y = a & b; | Controla y con el AND de a y b |
assign sum = a + b; | Calcula una suma de forma continua |
assign y = sel ? a : b; | Ternario: un multiplexor 2 a 1 |
assign {c, s} = a + b; | Captura el acarreo y la suma juntos |
assign y = ~en; | Controla un wire a partir de una señal invertida |
Bloques procedurales
always e initial ejecutan sentencias; la lista de sensibilidad controla cuándo.
| Sintaxis | Significado |
|---|---|
always @(*) begin ... end | Lógica combinacional (cualquier cambio en una entrada) |
always @(posedge clk) | Se ejecuta en cada flanco de subida del reloj (secuencial) |
always @(negedge clk) | Se ejecuta en cada flanco de bajada del reloj |
always @(posedge clk or posedge rst) | Bloque sincronizado con reset asíncrono |
initial begin ... end | Se ejecuta una vez en el tiempo 0 (testbenches, solo simulación) |
begin ... end | Agrupa varias sentencias |
#10 | Retrasa 10 unidades de tiempo (solo simulación) |
Bloqueante vs no bloqueante
Usa = para la lógica combinacional y <= para la lógica secuencial sincronizada.
| Sintaxis | Significado |
|---|---|
a = b; | Bloqueante: se ejecuta en orden, de inmediato |
a <= b; | No bloqueante: primero se leen todos los lados derechos y luego se asignan |
always @(*) y = a & b; | Combinacional: usa el bloqueante = |
always @(posedge clk) q <= d; | Un flip-flop: usa el no bloqueante <= |
Mezclar = y <= en un mismo bloque | Evítalo: es una fuente común de errores |
Control de flujo
Condicionales y bifurcaciones de varias vías dentro de los bloques procedurales.
| Sintaxis | Significado |
|---|---|
if (cond) ... else ... | Sentencia condicional |
if (a) x = 1; else x = 0; | If/else de una línea |
case (sel) ... endcase | Bifurcación de varias vías sobre un valor |
2'b00: y = a; | Un elemento de case |
default: y = 0; | Elemento de case de reserva |
for (i = 0; i < 8; i = i + 1) | Bucle (a menudo dentro de generate o de simulación) |
repeat (4) @(posedge clk); | Repite una sentencia N veces |
Patrones comunes
Componentes básicos que escribes una y otra vez, además de tareas de testbench.
| Patrón | Sintaxis |
|---|---|
| Flip-flop D | always @(posedge clk) q <= d; |
| Registro con reset | always @(posedge clk) if (rst) q <= 0; else q <= d; |
| Contador | always @(posedge clk) count <= count + 1; |
| Registro de estado de FSM | always @(posedge clk) state <= next_state; |
| Lógica de siguiente estado de FSM | always @(*) case (state) ... endcase |
| Imprimir un valor | $display("q = %b", q); |
| Imprimir al cambiar | $monitor("t=%0t q=%b", $time, q); |
| Finalizar la simulación | $finish; |
Cada elemento de la sintaxis de Verilog que necesitas, en una sola página. Esta hoja de trucos de Verilog es una referencia rápida para el lenguaje de descripción de hardware: declarar módulos y puertos, elegir tipos de datos, escribir lógica combinacional y secuencial, y los patrones de bloques always que describen circuitos reales.
La sintaxis aquí es Verilog estándar (IEEE 1364) y funciona en simuladores comunes como Icarus Verilog y Verilator. Copia lo que necesites o pruébalo en vivo en el playground de Verilog: escribe un módulo, simúlalo y ve la salida en tu navegador.
Preguntas frecuentes sobre la hoja de trucos de Verilog
¿Esta hoja de trucos de Verilog es gratis?
¿Cuál es la diferencia entre wire y reg?
wire modela una conexión física y debe controlarse de forma continua (mediante una sentencia assign o la salida de un módulo), así que lo usas para las redes combinacionales. Un reg mantiene su valor hasta que el código procedural lo cambia, así que lo usas para cualquier cosa que se asigne dentro de un bloque always o initial. A pesar del nombre, un reg no siempre se convierte en un registro de hardware; solo significa que el valor se establece de forma procedural.¿Cuál es la diferencia entre la asignación bloqueante y la no bloqueante?
=) se ejecuta de inmediato y en orden, como una sentencia de programación normal, así que úsala para la lógica combinacional en los bloques always @(*). La asignación no bloqueante (<=) evalúa primero todos los lados derechos y luego actualiza los lados izquierdos a la vez, lo cual modela correctamente los flip-flops, así que úsala en los bloques sincronizados always @(posedge clk). Mezclar ambas en un mismo bloque es una fuente clásica de errores de simulación.