Blocking assignment for clock divider

I came across the following systemverilog coding guideline:
guideline:Use blocking assignments for clock divider flip-flops. Sometimes non-blocking assignments create a race condition instead of preventing it.

Can someone explain this guideline with an example?

In reply to svishnu:
I would not say that they create race conditions. What they do is remove the synchronization between the the edges that supposed to be synchronized. Try this code with and without the NBA in the clock divider.

module top;
   bit clk, clkdiv;
   int A,B;
   always #5 clk = !clk;
   always @(posedge clk) clkdiv <= !clkdiv; // should be blocking

   always @(posedge clk) A <= A + 1;
   always @(posedge clkdiv) B <= A; // gets the updated value of A
   initial begin
      $monitor($time,,A,,B);
      #100 $finish;
   end
endmodule

The rule should be if you want to keep clocks synchronous in an RTL description, do not use non-blocking assignment in the clock path. This applies to gated clocks as well as clock dividers.

In reply to dave_59:
The above example shows very poor design practices because it utilizes derived clocks as clocks along with the master clock. This is an invitation to poor designs and problems. TOO MANY CLOCKS!!! Tricking the simulator does not help, sorry; GBGO !!!
Why not do something like what is done in good designs? below is my recommendations.


module top;
   bit clk, clkdiv;
   int A,B;
   always #5 clk = !clk;
   always @(posedge clk) clkdiv <= !clkdiv;  
 
   always @(posedge clk) A <= A + 1;
   always @(posedge clk && clkdiv) B <= A; // gets the current, non-updated value of A
   // BTW, this is how hardware works. 
   initial begin
      $monitor($time,,A,,B);
      #100 $finish;
   end
endmodule 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us


In reply to ben@SystemVerilog.us:

Your code produced the same result as Daves.
Did you mean something like this:
always @(posedge clk) if (clkdiv) D<=A;

In reply to bmorris:
I was thinking more of what real hardware does. Unless the methodologies changed, if you have designs clocked at derived clocks, you still want all the flops to be controlled by the faster clocks. There are some power considerations. The approaches I saw (that was many years ago) are as follows:

  • devices clocked with the master clock are actually clocked through 2 stages of NAND gates, and it is the delayed clocks that drives all the devices. Thus,
bit clk, clkn1, clk1, clkn2, clk2;
assign clkn= !clk;
assign clk1 = ! clkn;
always @(posedge clk1) A <= A + 1;
//
// For devices that use the clkdiv
assign clk2n=!(clk && clkdiv);
assign clk2 = !clk2n;
always @(posedge clk2) B<=A;
// Now, what is above is really at the gate level.  At the RTL,
// both of these would work.
always @(posedge clk) if (clkdiv) B<=A; // OK too
always @(posedge clk && clkdiv) B <= A;

You seemed to stress in your original post the need of derived clocks. What I was saying is that one has to be very careful in using derived clocks as actual clocks rather than as clock enables. For synthesis, one needs to use the styles that are compatible with the synthesis tools.
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us


In reply to ben@SystemVerilog.us:

I understand. When I learned synchronous fpga design almost a decade ago, I was taught to avoid gated clocks & latches, and use clock enables. And “use only 1 clock”, and even if you have more than one clock “use only 1 clock!” (like you mentioned). I’m not included PLLs and other external clocks in that grouping. I would never create a clock and then feed that directly into a circuit; that can cause skew and I’m sure the tool would warn you.