Realmente depende si quieres c
como reg
o wire
. Ambos enfoques funcionan, pero reg
debe asignarse en el bloque de procedimiento, mientras que wire
necesita una declaración assign
(o asignada en la declaración).
Como reg
, debe definirse dentro de un bloque de procedimiento. Tales como:
reg [1:0] c;
always @* begin
c = {a,b};
end
o:
reg [1:0] c;
always @* begin
c[1] = a;
c[0] = b;
end
No hay diferencia funcional o de comportamiento con los dos bloques siempre, es solo una cuestión de preferencia por la legibilidad.
Como wire
puede declararse y asignarse en una línea:
wire [1:0] c = {a,b};
O declarado y asignado en líneas separadas:
wire [1:0] c;
assign c = {a,b};
O declarado con cada bit asignado en líneas separadas:
wire [1:0] c;
assign c[0] = b;
assign c[1] = a;
Todos los ejemplos anteriores simularán y sintetizarán lo mismo.
Con wire
si hay dos controladores en conflicto en la misma red, habrá una X en la simulación. Con reg
, la última asignación gana en simulación y no en síntesis. El método assign
por bit tiene más sobrecarga de simulación, pero normalmente solo se nota con diseños muy grandes.
No se requiere que los simuladores evalúen siempre los bloques en el tiempo 0, por lo que podría haber una pequeña falta de coincidencia. Los resultados serán idénticos después de que los cambios de estímulo después del tiempo-0. (Nota: el always_comb
de SystemVerilog siempre realiza una evaluación de tiempo 0 y arroja errores, hay otro controlador posible en uno de los bits que asigna).
Para un módulo pequeño que solo tiene lógica combinacional simple; realmente no importa usar wire
con assign
vs reg
con always
. Con un FSM, me gusta poner casi toda mi lógica de combinación en un gran always @*
. Encuentro que esto generalmente proporciona el mejor rendimiento de simulación y el mejor resultado de síntesis con mi conjunto de herramientas. Ocupacionalmente, dividí el always @*
en partes separadas always @*
al tratar con señales de entrada asíncronas de ruido en particular.