2
\$\begingroup\$

For the following code on simulation, I am getting stable_4_clk[0]=1 at 30 ns and 0 at 40 ns. I thought it would be vice-versa. What is the reason for stable_4_clk[0]=1 at 30ns and 0 at 40ns?

Code link: https://edaplayground.com/x/TLtT

module tb;
  
  logic [3:0] stable_4_clk;
reg clk, rstn, din;

always begin clk=1; #5 clk=0; #5; end

initial begin
  rstn=0;
  #10 rstn=1;
  #5 din=1;
  #5 din=0;
  #10 din=1;
  #55 din=0;
  #10 $finish;
end

always@(posedge clk, negedge rstn) 
  if(!rstn) stable_4_clk<=0;
  else
    if(din==$past(din)) stable_4_clk<={stable_4_clk[2:0],1'b1};
     else  stable_4_clk<={stable_4_clk[2:0],1'b0};
  
  initial begin
   $dumpfile("dump.vcd"); 
   $dumpvars(0);
  end

endmodule

enter image description here

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

The Verilog code has a simulation race condition, which means that the simulation results are often unpredictable.

In some cases, it is fine to tolerate this uncertainty, but I suspect that is not the case for you.

The issue is that you are changing din at the same time as the clk rising edge. Since you are sampling din at that edge using this sensitivity list:

always@(posedge clk, negedge rstn) 

the simulator does not guarantee that it will sample din before or after the posedge of clk. It is indeterminate, and the simulator is allowed to choose one or the other. This can vary from simulator to simulator, or even between different versions of the same simulation software.

If you want din to be truly synchronous to the clock (and I suspect you do), then you need to drive din the same way you drive stable_4_clk, namely:

  • @(posedge clk)
  • Using nonblocking assignments (<=)

Currently, you drive din with # delays and blocking assignments (=). This leads to the simulation race condition. This is a way to code the testbench to avoid the race condition:

initial begin
    rstn=0;
    #10 rstn=1;

    @(posedge clk);
    din <= 1;

    @(posedge clk);
    din <= 0;

    @(posedge clk);
    din <= 1;

    repeat (5) @(posedge clk);
    din <= 0;

    #10 $finish;
end

With those changes, I see stable_4_clk[0] change from 0 to 1 at time 50ns. This is the expected time since it is the first clock cycle after din has been stable for at least 2 clock cycles.

waves

Using $past is handy, but one disadvantage is that you can not see the value of $past(din) in the waveforms; you must assume its value when debugging.

An alternate is to add logic for din edge detection, which is very common.

\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.