Reputation: 1262
I have the following MWE:
module test(
input wire clock,
input wire start
);
reg [7:0] x = 8'b10101010;
reg processing = 0;
wire [7:0] x_wire0 = x;
wire [7:0] x_wire1 = {4'hf, x};
wire [11:0] x_wire2 = {4'hf, x};
always @(posedge clock) begin
if (start & ~processing) begin
x = 8'h0f;
processing = 1;
end
$display("---> x=%h x_wire0=%h x_wire1=%h x_wire2=%h",
x, x_wire0, x_wire1, x_wire2);
end
endmodule
with the testbench
module test_test();
reg clock = 0;
reg start = 0;
test test(
.clock(clock),
.start(start)
);
always #5 clock = ~clock;
initial begin
$monitor("%b %b", clock, start);
#20 start = 1;
#20 start = 0;
#200 $finish;
end
endmodule
which using Icarus Verilog 0.9.7 gives me the output
0 0
---> x=aa x_wire0=aa x_wire1=aa x_wire2=faa
1 0
0 0
---> x=aa x_wire0=aa x_wire1=aa x_wire2=faa
1 0
0 1
---> x=0f x_wire0=0f x_wire1=aa x_wire2=f0f
1 1
0 1
---> x=0f x_wire0=0f x_wire1=0f x_wire2=f0f
1 1
0 0
...
I wonder why x_wire1 is not updated until the next clock tick and whether there are any rules (of thumb) to avoid these kind of situations. If I use a "#0" before the display command, it is updated.
Upvotes: 1
Views: 1974
Reputation: 42698
If you change your $display
to $strobe
, you will get the results you are looking for. It truly is a race condition in simulation if the wires have a chance to get updated before the $display
. $strobe
delays its output until the end of the time slot after the wires have settled. The assignments to the wires are essentially independent processes.
Another option is to use non-blocking assignments to x
. You should always use non-block assignments to variables in sequential logic that will be read by another process anyways. Then your $display is always printing values from the previous clock cycle.
And finally, you can use another always
block just for the $display
statement the uses the negative edge of the clock.
Upvotes: 2