I am having trouble with simulation of the nonblocking assignment delay in the
A simple example: assignment of the input
in to an intermediate wire
tmp, which in turn is used to set the output register
out on a rising clock edge.
As far as I know, in a hardware implementation of such a module, the
tmp signal will switch almost immediately, i.e., in the same clock cycle as
in changes. On the other hand, the
out signal will switch one clock cycle after
tmp (and this is what I usually observe on the ILA core). However, I am not always able to properly simulate this delay.
For example, I simulated two such systems in Xilinx Vivado (see the code below):
out2. The only difference is in the testbench:
in2 is generated using an additional
@ (posedge clk) expression. The waveforms of
in2 appear to be identical, but somehow they cause a different effect:
out2 does appear with the expected delay, while
out1 does not.
Additionally, if the intermediate signal
tmp2 is removed (and the assignment on a rising clock edge is
out2 <= in2), the delay of
out2 also disappears. This makes me a bit confused, as I do not understand why such a simple continuous assignment would affect the timing to a degree that the delay vanishes.
I wonder how can this effect be reliably controlled. Specifically, I would like the simulated waveforms to work in line with the signals that occur in the hardware. This would speed up the debugging process as with minor changes I could rely on the simulation results, and it would no longer require re-synthesizing the entire project.
`timescale 1ns / 1ps module test_module ( input clk, in1, in2, output tmp1, tmp2, output reg out1 = 1'b0, output reg out2 = 1'b0 ); assign tmp1 = in1, tmp2 = in2; always @ (posedge clk) begin out1 <= tmp1; out2 <= tmp2; end endmodule
`timescale 1ns / 1ps module test_module_tb; localparam integer period = 10; localparam integer cycle = 2 * period; reg clk = 1'b1, in1 = 1'b0, in2 = 1'b0; wire tmp1, tmp2, out1, out2; always #(period/2) clk = ~clk; always #(cycle) in1 = ~in1; always #(cycle) @(posedge clk) in2 = ~in2; test_module UUT (.clk(clk), .in1(in1), .in2(in2), .tmp1(tmp1), .tmp2(tmp2), .out1(out1), .out2(out2)); endmodule