1

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.

SKB
  • 11
  • 1
  • 1
    you are missing `w1` and `rst` (as well as `w0`) from the sensitivity list. Use `always @*` instead to avoid such issues. – Serge Dec 17 '20 at 11:47

0 Answers0