Electronic – When to use blocking and non-blocking assignments

verilog

I am having a really hard time to understand where to use blocking and non-blocking assignments. I have read many answers regarding this on this site and have also referred to book on Verilog by "Samir Palnitkar". But when I sit to actually implement some circuit, I am not able to decide which one to use.

I have following questions regarding this:

a) In a sequential circuit, say Synchronous 4-bit counter implemented using JK flip-flops, we need to use two & gates and the output of one & gate is used as the input of the other. Now, I follow the thumb rule that I should use <= for sequential circuts and should not mix = and <= assignments in an @always block.

always @(posedge clk or posedge rst)
    begin
        if(en)
        begin
            if(rst)
                q<=4'b0000;
            else
            begin
                q[0]<=(~q[0]);

                if(q[0]==1)
                    q[1]<=(~q[1]);

                if(q[0]&q[1]==1)
                    q[2]<=~q[2];

                if(q[0]&q[1]&q[2]==1)
                    q[3]=~q[3];
            end
        end
    end

In the above code for the same circuit, what if I want to store the o/p of q[0]&q[1] in another register and then use it to find q[0]&q[1]&q[2]? If I use <=, I may end up getting wrong value of q[0]&q[1]&q[2].

How should I store the intermediate outputs and use them as inputs in the sequential circuit (May be needed for complex circuits)?

b) What are some rules/guidlines that I should follow so that I don't encounter some race condition or other undesired o/p from my code?

Best Answer

You are not understanding the rule correctly. You must not mix = and <= to the same variable within an always block.

And yes, generally you should use non-blocking <= assignments to sequential logic. You must us a non-blocking assignment if one always @(posedge clock) block writes, and another always @(posedge clock) reads the same variable, or combinatorial expression of the same variable).

The synthesis tool makes the variable sequential if one of the following is true:

  1. The variable is written with a non-blocking assignment <=
  2. The variable is read before written within the block
  3. The variable is read somewhere else outside the block

Otherwise it becomes combinational logic.