Is it possible and/or useful to ever use a continuous assignment in a Verilog procedure? For example, would there ever be any reason to put an assign
inside of
It is called procedural continuous assignment. It is the use of an assign
or force
(and their corresponding counterparts deassign
and release
) within procedural block. A new continuous assignment process is created when the line is reached in the procedural block. assign
can be applied to register types such as reg
, integer
, and real
. force
can be applied to registers and nets (i.e. wire
s). It has been part of the LRM since 1364-1995.
Procedural continuous assignments are synthesizable, by most tools. However it is recommend to limit the use to behavior modeling of an analog block, test bench files, or fixing RTL<->gate functional mismatches.
always @* assign data_in = Data;
always @* data_in = Data;
always @(posedge clk) assign data_in = Data;
always @(posedge clk)
enable = 1;
always @*
if (enable==1) data_in = Data;
A valid use of procedural continuous assignment would be should be applited to the following:
always @(posedge clk or negedge rst_n, negedge set_n) begin
if (!rst_n) q <= 1'b0;
else if (!set_n) q <= 1'b1;
else q <= d;
end
It will synthesize to a flop with an asynchronous set and reset with priority to reset. In simulation however the model is inaccurate if rst_n
and set_n
are both low then rst_n
goes high. q
should go to 1 the the asynchronous set is still enabled, but nothing to trigger in in the sensitivity list. This is a well documented issue with Verilog. It is the one case procedural continuous assignment are allowed in RTL when used with the translate off keyword your synthesizer. The release
/deassign
allows the the register/wire to be assigned in the usual manner.
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) force q = 1'b1;
else release q;
// translate_on
OR (currently valid but discouraged)
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) assign q = 1'b1;
else deassign q;
// translate_on
Using assign
/deassign
in this manner is being considered to be depreciated in future IEEE 1800 release. IEEE Std 1800-2005 § 25.3, IEEE Std 1800-2009 § C.4.2 and IEEE Std 1800-2012 § C.4.2 recognizes assign
used this way causes confusion and is the source of errors. Use force
/release
if procedural continuous assignment as needed.
In generate using procedural continuous assignment (with force
/release
) should only be used if absolutely necessary. Alternative approaches are more reliable.
Combinational logic on reg
:
always @(sel)
if (sel) assign reg1 = func1(x,y,z);
else assign reg1 = func2(a,b,c);
Solution:
always @* // <- IEEE Std 1364-2001 construct
if (sel) reg1 = func1(x,y,z);
else reg1 = func2(a,b,c);
Combinational logic on wire
:
always @(sel)
if (sel) force wire1 = func1(x,y,z);
else force wire1 = func2(a,b,c);
Solution:
assign wire1 = sel ? func1(x,y,z) : func2(a,b,c);
Sequential logic:
always @(posedge clk)
if (sel) assign reg2 = func1(x,y,z);
else assign reg2 = func2(a,b,c);
Solution (assuming original functionality is wrong):
always @(posedge clk)
if (sel) reg2 <= func1(x,y,z); // Non-blocking assignment !!!
else reg2 <= func2(a,b,c);
Solution (assuming original functionality is correct):
reg flop_sel;
always @(posedge clk)
flop_sel <= sel; // Non-blocking assignment !!!
always @*
if (flop_sel) reg2 = func1(x,y,z); // Blocking assignment !!!
else reg2 = func2(a,b,c);