0
votes

The code below is a simpler case of what I'm writing.

module bar will do something to a according to operation. The problem is, I can't get result correctly assigned (which should be assigned after output b of foo1).

I have found a workaround, just add #1 before result = r1. I wonder what is the correct way to synchronize between modules?

module foo1(
  input a,
  output reg b
);
  always@(a)
    b = a;
endmodule

module foo2(
  input a,
  output reg b
);
  always@(a)
    b = ~a;
endmodule

module bar(
  input a,
  input operation,
  output b
);
  reg result;
  assign b = result;

  wire r1, r2;
  foo1 submod1(a, r1);
  foo2 submod2(a, r2);

  always@(a or operation) begin
    case (operation)
      1'b0:
        result = r1;
      1'b1:
        result = r2;
    endcase
  end

  initial begin
    $dumpfile("foobar.vcd");
    $dumpvars(0, r1);
    $dumpvars(0, r2);
    $dumpvars(0, result);
    $dumpvars(0, operation);
  end
endmodule

module test;
  reg a, op;
  wire r;
  bar mod(a,op,r);

  integer i;
  initial begin
    a = 0;
    op = 0;
    for (i=0; i<8; i=i+1)
      #10 a = ~a;
  end
endmodule
2

2 Answers

1
votes

The reason you might not be seeing proper propagation of the result is because your sensitivity list for result is not complete. You include a and operation by you really need to include r1 and r2 to have correct combinational logic. If you add them to the sensitivity list, it should operate as expected:

always@(operation or r1 or r2) begin
  case (operation)
    1'b0:
      result = r1;
    1'b1:
      result = r2;
  endcase
end

However, it is best if you cannot use SystemVerilog constructs like always_comb to at least use the Verilogs always @(*) to do combinational logic. That way, you dont risk missing sensitivity list items as you did this time.

1
votes

Your sensitivity list to assign result is incorrect. always@(a or operation) should be always@(r1 or r2 or operation) or always @*.

Verilog simulates everything out of order except for code placed in a procedural block (begin-end). This means always@(a or operation) can execute before r1 and r2 are updated.

For combinational logic I recommend using always @* (or always @(*) which is equivalent). This is a auto sensitivity list (ie figure out what should be in the sensitivity list for you) introduced in IEEE Std 1364-2001 which all modern simulator support. If you need to follow the IEEE Std 1364-1995 the use always@(r1 or r2 or operation)