Keywords: deassign, force, release
Procedural continuous assignment is a type of procedural assignment. This assignment statement can replace all other assignments to wire or reg, overwriting the current value of variables of type wire or reg.
Unlike procedural assignment, the expression of a procedural continuous assignment can be continuously driven into variables of type wire or reg. That is, when a procedural continuous assignment takes effect, any change in an operand of the right-hand expression will cause the procedural continuous assignment statement to re-execute.
There are mainly two types of procedural continuous assignment: assign-deassign and force-release.
assign, deassign
assign (procedural assignment operation) and deassign (cancel procedural assignment operation) represent the first type of procedural continuous assignment statement. The assignment target can only be a register or register array, not a wire type variable.
During the assignment process, the register is continuously assigned, and the value in the register is retained until it is reassigned.
For example, a D flip-flop with a reset terminal can be described with the following code:
Example
input rstn,
input clk,
input D,
output reg Q
);
always @(posedge clk or negedge rstn) begin
if(!rstn) begin //Q = 0 after reset effective
Q <= 1'b0 ;
end
else begin
Q <= D ; //Q = D at posedge of clock
end
end
endmodule
In the following, rewrite it with assign and deassign to accomplish the same functionality.
That is, when the reset signal is 0, the Q terminal is assigned by the assign statement and always outputs 0.
When the reset signal is 1, the Q terminal is de-assigned by the deassign statement and is reassigned at the rising edge of the clock.
Example
input rstn,
input clk,
input D,
output reg Q
);
always @(posedge clk) begin
Q <= D ; //Q = D at posedge of clock
end
always @(negedge rstn) begin
if(!rstn) begin
assign Q = 1'b0 ; //change Q value when reset effective
end
else begin //cancel the Q value overlay,
deassign Q ; //and Q remains 0-value until the coming of clock posedge
end
end
endmodule
force, release
force (force assignment operation) and release (release forced assignment) represent the second type of procedural continuous assignment statement.
The usage and effects are similar to assign and deassign, but the assignment target can be either a reg type variable or a wire type variable.
Because it is an unconditional forced assignment, it is generally used in interactive debugging processes and should not be used in design modules.
When force is applied to a register, the current value of the register is overwritten; at release, the register value will continue to retain the value from the forced assignment. After that, the register value can be changed by the original procedural assignment statements.
When force is applied to a net, the net value is also forcibly assigned. However, once the net variable is released, its value immediately becomes the original driven value.
To intuitively observe the difference of forced assignment between the two types of variables, use the counter counter10 from the first section as the design module, and the testbench is designed as follows.
Example
module test ;
reg rstn ;
reg clk ;
reg [3:0] cnt ;
wire cout ;
counter10 u_counter (
.rstn (rstn),
.clk (clk),
.cnt (cnt),
.cout (cout));
initial begin
clk = 0 ;
rstn = 0 ;
#10 ;
rstn = 1'b1 ;
wait (test.u_counter.cnt_temp == 4'd4) ;
@(negedge clk) ;
force test.u_counter.cnt_temp = 4'd6 ;
force test.u_counter.cout = 1'b1 ;
#40 ;
@(negedge clk) ;
release test.u_counter.cnt_temp ;
release test.u_counter.cout ;
end
initial begin
clk = 0 ;
forever #10 clk = ~ clk ;
end
//finish the simulation
always begin
#1000;
if ($time >= 1000) $finish ;
end
endmodule // test
The simulation results are as follows.
As can be seen from the figure, when cnt_temp equals 4 (80ns), cnt_temp is forced to 6, and cout is forced to 1.
At release (120ns), cnt_temp is a register type, still retaining its original value unchanged; only when the clock rising edge performs addition assignment on it, the value becomes 7.
At 120ns, however, since cout is a net type variable, its value cannot be saved. In the original counter10 model, there is a driving statement:assign cout = (cnt_temp==4'd9), so the cout value becomes 0.

Source Code Download
Download