I'm new to Verilog and I could very well be mistaken, but I've been writing Verilog code under the assumption that a wire and its assignment RHS are interchangeable. I.e., if you have the line
assign w = exp;
for some wire w
and expession exp
, you can replace any occurrence of w
with exp
without changing the module behavior. But I've ran into an instance that seems to violate this assumption. The module definition is as follows:
module foo
(
input rst,
input i0,
input i1
);
reg r0;
reg r1;
reg r2;
wire w0;
wire w1;
assign w1 = i1;
assign w0 = (w1 == r2);
always @(i0, r0) begin
if (i0 == 1 && r0 == 0 && !rst) begin
r1 <= (w1 == r2); // with this line, the value of r1 gets correctly updated
// r1 <= w0; // update fails when this line is used
end
end
always @(rst)
if (rst) begin
r0 <= 0;
r1 <= 0;
r2 <= 0;
end
endmodule
And this is the test bench I'm using:
module foo_tb();
reg rst;
reg i0;
reg i1;
foo DUT (
.rst(rst),
.i0(i0),
.i1(i1)
);
initial begin
i0 = 0;
i1 = 1'b1;
rst = 1;
#5
rst = 0;
#5
i0 = 1;
i1 = 1'b0;
#5
i0 = 0;
#5
$finish;
end
endmodule
As indicated in the comments, using the line r1 <= (w1 == r2)
makes the value of r1
get correctly updated in simulations, but using r1 <= w0
does not. I wonder where this difference comes from?
My hunch is that it might have to do with r2
being a register instead of a wire, but I'm puzzled. If there is some simple maxim I can follow to avoid these kinds of behaviors, it would be really useful.
I'm using Vivado 2020.2 for simulations, if that is relevant.