Dos nombres, un trabajo
Cada señal en Verilog tiene un tipo. Los dos tipos que conocerás primero son wire y reg. Los dos pueden mantener un valor. Los dos pueden ser de un bit o multibit. La diferencia no es sobre qué es la señal - es sobre quién la excita.
- Las señales
wirese excitan fuera de bloques procedurales - por sentenciasassign, por las salidas de submódulos, o por puertos de entrada de módulo. - Las señales
regse excitan dentro de bloques procedurales -initialoalways.
Esa es toda la regla. Los nombres de las palabras clave son raros porque preceden a la forma moderna de escribir Verilog. reg no siempre se convierte en un registro en hardware. Sigue leyendo para ver por qué.
Wire: la conexión continua
Un wire es un wire eléctrico. Lleva lo que sea que su driver esté produciendo, continuamente. Dos formas en las que un wire es excitado:
Tres cosas a observar:
yyzse declaranwireen el módulo ywirede nuevo en el testbench.- Se excitan con
assign- esa es la forma de asignación continua. El lado derecho del=se vuelve a calcular cuando cualquier señal en él cambia. - No podemos escribir
y = a & bdentro de un bloquealwaysmanteniendoycomowire. El compilador lo rechazaría.
Si olvidas la palabra clave wire, Verilog declara implícitamente la señal como un wire de un solo bit por ti - lo que a veces es conveniente y a veces es un bug silencioso. La mayoría de los equipos habilitan una opción de la herramienta que da error en wires implícitos. Sé explícito y evita la trampa.
Reg: almacenamiento dentro de un bloque procedural
Un reg es una señal a la que asignas dentro de initial o always. El nombre es una reliquia de los primeros días del lenguaje cuando "reg" sonaba a "registro"; en uso moderno un reg es solo el tipo de cualquier señal a la que el código procedural escribe.
count es reg dentro del módulo (porque el bloque always le escribe) y wire en el testbench (porque el puerto de salida del DUT lo excita). Misma señal, roles distintos, tipos distintos en cada scope.
Por qué "reg" no siempre significa "registro"
Aquí está la trampa más común de principiantes. Este módulo declara y como reg - pero el hardware sintetizado no contiene un flip-flop:
El bloque always @(*) es sensible a cualquier cambio de entrada. Es combinacional. Una herramienta de síntesis ve ese patrón y produce una puerta AND - sin flip-flop, sin reloj, solo lógica. La palabra clave reg es puramente un requisito sintáctico porque y se asigna dentro de un always.
Para conseguir un flip-flop real, el bloque always tiene que ser sensible a un flanco de reloj:
always @(posedge clk) begin
q <= d;
end
Ese es el patrón "sintetizador, por favor haz un flip-flop": lista de sensibilidad sincronizada por reloj, asignación no bloqueante. Misma palabra clave reg, hardware completamente distinto. Cubrimos la distinción en Always Block y Blocking vs Non-blocking.
La decisión en la práctica
Cada vez que declaras una señal, pregunta: ¿cómo la voy a excitar?
- ¿Excitar con
assign? →wire. - ¿Conectar al puerto de salida de un submódulo? →
wire. - ¿Puerto de entrada de módulo? →
wire. (Las entradas siempre son wire.) - ¿Excitar desde
initialoalways? →reg. - ¿Puerto de salida de módulo excitado por código procedural? →
output reg. - ¿Puerto de salida de módulo excitado por
assign? →output wire. (O simplementeoutput- la dirección sola por defecto va a wire.)
Ese árbol de decisión cubre cada situación que vas a encontrar en Verilog clásico.
Conflictos de drivers
Las señales wire pueden tener varios drivers en teoría - así es como funcionan los buses tri-state, donde varios módulos pueden excitar el mismo wire y los inactivos van a alta impedancia (z). Para lógica ordinaria, dos sentencias assign escribiendo el mismo wire producen comportamiento indefinido:
assign y = a;
assign y = b; // BAD - y has two drivers
El simulador puede elegir uno, puede dejar la señal en X, depende de la herramienta. De todos modos es un bug. Un driver por wire a menos que estés construyendo un bus explícitamente.
Las señales reg solo pueden ser excitadas desde un bloque procedural. Dos bloques always ambos asignando al mismo reg es un error de síntesis y extraño en simulación. Misma regla: un driver.
La actualización de SystemVerilog: logic
SystemVerilog (el superset al que evolucionó Verilog) añade una única palabra clave que reemplaza a las dos: logic. Una señal logic puede ser excitada por assign o por un bloque procedural - pero no por ambos - y el compilador te detiene de configurar accidentalmente un bug de múltiples drivers.
module modern(input logic a, input logic b, output logic y);
assign y = a ^ b;
endmodule
Si estás empezando un proyecto desde cero y tu herramienta soporta SystemVerilog (que el editor de esta página lo hace, con -g2012), usar logic en todas partes simplifica las reglas. Los archivos .v clásicos todavía necesitan la división wire/reg, y verás los dos estilos en código real para siempre.
Qué viene a continuación
El siguiente doc - Vectors and Arrays - toma los mismos dos tipos y muestra cómo hacerlos multibit. Anchos de bus, rangos, dimensiones packed, la diferencia entre un vector de bits y un array de vectores. Todas las cosas que necesitas antes de poder construir algo más grande que un sumador de un bit.
Preguntas frecuentes
¿Cuál es la diferencia entre wire y reg en Verilog?
wire y reg ambos mantienen un valor de señal en cada instante en simulación, pero eliges entre ellos basándote en quién excita la señal. Un wire se excita desde fuera de un bloque procedural - por un assign o por la salida de un submódulo. Un reg se excita desde dentro de un bloque initial o always. Los nombres son históricos y engañosos; reg no siempre significa 'registro'.
¿Significa reg en Verilog un flip-flop?
No necesariamente. Un reg solo sintetiza a un flip-flop cuando su bloque always es sensible a un flanco de reloj y usa asignación no bloqueante. Un reg asignado dentro de un bloque always @(*) combinacional sintetiza a lógica combinacional plana. La palabra clave elige el tipo de dato Verilog, no el hardware.
¿Cuándo debería usar wire vs reg?
Regla práctica: si vas a excitar la señal con assign o conectarla a un puerto de salida de un submódulo, usa wire. Si vas a asignarle dentro de un bloque always o initial, usa reg. Las entradas a un módulo son siempre wire. Las salidas son wire si las excita un assign y reg si las excita un bloque procedural.
¿Puedes asignar a un wire dentro de un bloque always?
No - eso es un error de sintaxis. Las señales wire solo pueden ser excitadas por asignaciones continuas (assign) o conectadas como salida de una instancia de submódulo. Cualquier cosa dentro de initial o always tiene que tener como destino un reg (o en SystemVerilog, un logic). El compilador atrapa esto y se queja de una 'left-hand side type mismatch'.
¿Qué es logic en SystemVerilog?
logic es la unificación de SystemVerilog de wire y reg. Puede ser excitado por una asignación continua o por un bloque procedural (pero no por ambos al mismo tiempo). El código moderno usa cada vez más logic por todas partes y olvida la distinción wire/reg. Los archivos Verilog clásicos todavía necesitan elegir.