ms_stud
ms_stud

Reputation: 381

Implementing hardware in verilog: = vs <=

Suppose I have the following code in Verilog:

module A (clk,a,c);

input clk;
input a;
output c;

wire clk;
wire a;
reg c;
reg b;

always @(posedge clk)
begin
   b = a;
   c = b;
end

endmodule

Let's assume that this module implements some Flip Flop which has two input (a and clk) and has one output (c)

I have read that the main difference between the operator= and the operator<= is that when using the operator= the commands are executed by one after another in sequentially order (meaning: b get the value of a and c gets the value of b) and when using operator<= the commands are executed in the same time (meaning: b gets the value of a and c gets the value of b in the same time).

Now , my question is:

can I say that in case we use operator= then b gets the new value of a and c gets the old value of b (a value in one clock period before current) and in case we use operator<= then b gets the new value of a and c gets also the new value of a?

Somehow it is make sense to me but this is an always block meaning after it in both cases the values of c should be the a that was received in the current clock period

Thank you, Michael

Upvotes: 0

Views: 1608

Answers (2)

Serge
Serge

Reputation: 12354

Verilog simulation consists of micro-steps (or delta cycles), related to the events. Event is actually any change of a value of a variable which causes re-evaluation of other blocks. So, the delta cycle is a step which requires for the model to get quiescent.

The delta cycle itself consists of multiple scheduling buckets, executed one after another in the cycle. In the very simplified view there are at least a blocking bucket and non-blocking bucket. All blocking assignment are evaluated in the first bucket, all non-blocking - in the second.

So, in your case

always @(posedge clk)
begin
   b = a;
   c = b;
end

b gets evaluated in the first bucket and c is too, so it becomes the value of a. So, a was 1 then value of b will be 1, and the value c will also become '1' in the first bucket.

it you use non-blocking assignments, verilog will run in the first bucket but it will just schedules execution of the non-blocking assignments to be performed in the second bucket. So, in this code

always @(posedge clk)
begin
   b <= a;
   c <= b;
end

b will be scheduled to get value of a int he second bucket, c will be scheduled to become value of b in the second bucket. But the latter schedules an assignment of the current value of b, not the one which will be evaluated in the second bucket.

So, in above case the value of a was 1 and the value of b was 0, c will become 0 in the second bucket.

Of course, if c causes more first-bucket types of events, verilog will return to the first bucket and evaluate all events again. In reality there are more than 2 buckets in verilog and even more in system verilog.

There are certain reasoning for using blocking and non-blocking assignments and why they exist in verilog. But for simplicity you should follow a simple methodology: all outputs of state elements, like flops and latches must be assigned using non-blocking assignments, all combinatorial logic and clocks should use blocking assignments. This would save you from tidious debugging of races and glitch effects. So, in your case, assuming that b is just an intermidiate node in your flop, the following code should be used:

always @(posedge clk)
begin
   b = a;
   c <= b;
end

In this case, b will become value of a immediately int he first bucket, but the output of this flop c will be assigned using the non-blocking assignment according to the industry-wide methodology,

Upvotes: 0

dave_59
dave_59

Reputation: 42698

When you use a blocking assignment, the order of the reference(read) versus the assignment(write) within a block makes a difference in its implementation. In your example, you do an write to b, then it gets read. So b is essentially a temporary variable representing combinational logic. But if you read a variable before it gets written within the block, you get the value from the previous cycle; the output from the flip-flop.

When using non-blocking assignments, the order no longer matters - you always get the value from the previous cycle. And this is why you must use non-blocking assignments when you have multiple always @(posedge clock) when one block writes and other blocks read the same variable, you always get the value from the previous cycle. If you were to use a blocking assignment, in simulation there is no guaranteed ordering between the read and the write.

Upvotes: 0

Related Questions