En Verilog, wire
no puede almacenar un valor, solo se puede usar para conectar dos partes de un circuito.
Para poder ser utilizado en un bloque de procedimiento (como un bloque always
, o un bloque initial
, etc.), una variable debe poder almacenar un valor, incluso si es solo durante el procesamiento del bloquear. Como tal, no puede asignar un valor a un wire
dentro de un bloque de procedimiento porque no puede almacenar un valor.
En su caso, está utilizando su salida en un bloque always
, por lo que su salida no puede ser un cable. Si no se especifica, de lo contrario, se supone que una salida es un tipo wire
. Aquí es donde se produce el error. Para realizar la asignación en un bloque always
, por lo tanto, debe declarar explícitamente la salida como reg
(es decir, output reg
).
Para expandir el punto "¿Por qué necesito un registro si esta funcionalidad se puede implementar utilizando lógica combinacional con primitivos?":
Recuerda que Verilog es solo un lenguaje de descripción. Puede declarar las cosas de muchas maneras diferentes, y no necesariamente una descripción solo para los FPGA, sino también para la simulación y otros dispositivos. Como tal, lo que se infiere del código depende de la situación.
Un bloque always
en lo que concierne a Verilog se ejecuta línea por línea, lo que significa que cualquier cosa que se asigne dentro del bloque siempre debe poder almacenar un valor temporalmente durante la ejecución del bloque, y dependiendo del código después de la ejecución también.
Si este almacenamiento representa o no registros, latches, o simplemente lógica combinacional simple, depende de cómo sintetice, en su mayor parte, hasta la herramienta de síntesis y no algo definido en la especificación de Verilog. Esta es la razón por la que, independientemente de lo que suceda en el bloque, la especificación de Verilog simplemente ordena que cualquier variable utilizada en un bloque de procedimiento debe poder almacenar un valor.
En respuesta a su comentario, hay formas no procedimentales de hacer cosas que no requieren registros; cualquier circuito combinacional puede definirse sin la necesidad de bloques de procedimientos.
Un ejemplo en su caso sería utilizar el operador ternario con una declaración de asignación continua:
assign O = SEL ? (A - B) : (A + B);
Cuando SEL
es 1, O
se asigna a (A-B)
, de lo contrario, O
es (A+B)
.