To:
Http://hi.baidu.com/zhang_bi/blog/item/57edb701a9da6b00728b65db.html
There are two types of value assignment statements in OpenGL:Blocking value assignment statement ("= ")AndNon-blocking value assignment statement ("<= "). Correct use of the two assignment statements is very important for the design and simulation of the Tilde. The following example shows the difference between blocking and non-blocking assignment.
Let's take a look at several paragraphsCodeAnd the corresponding circuit:
HDLSource code |
Corresponding RTL Circuit |
Module shifter1 ( CLK, D, Q3 ); Input CLK; Input [7:0] D; Output [7:0] Q3; Reg [7:0] Q3, q2, Q1;
Always @ (posedge CLK) Begin Q1 = D; Q2 = Q1; Q3 = Q2; End Endmodule |
▲We can see that Q1 and Q2 have been optimized. |
Module shifter2 ( CLK, D, Q3 ); Input CLK; Input [7:0] D; Output [7:0] Q3; Reg [7:0] Q3, q2, Q1;
Always @ (posedge CLK) Begin Q1 <= D; Q2 <= Q1; Q3 <= Q2; End Endmodule |
|
Module shifter3 ( CLK, D, Q3 ); Input CLK; Input [7:0] D; Output [7:0] Q3; Reg [7:0] Q3, q2, Q1;
Always @ (posedge CLK) Begin Q3 = Q2; Q2 = Q1; Q1 = D; End Endmodule |
|
Module shifter4 ( CLK, D, Q3 ); Input CLK; Input [7:0] D; Output [7:0] Q3; Reg [7:0] Q3, q2, Q1; Always @ (posedge CLK) Begin Q1 <= D; Q2 = Q1; Q3 = Q2; End Endmodule |
|
Module shifter5 ( CLK, D, Q3 ); Input CLK; Input [7:0] D; Output [7:0] Q3; Reg [7:0] Q3, q2, Q1;
Always @ (posedge CLK) Begin Q1 <= D; Q2 <= Q1; Q3 = Q2; End Endmodule |
|
Module shifter6 ( CLK, D, Q3 ); Input CLK; Input [7:0] D; Output [7:0] Q3; Reg [7:0] Q3, q2, Q1; Always @ (posedge CLK) Begin Q1 <= D; Q2 = Q1; Q3 <= Q2; End Endmodule |
|
From the above example, we can see that in blocking assignment statements, the order of values is very important, while in non-blocking assignment statements, the order of values is not important.
The following is a detailed analysis.Semantic nature of blocking and non-blocking assignment:
Blocking: The next statement is executed only after "right calculation" and "Left Update" are complete;
Non-blocking: the execution of the current statement does not block the execution of the next statement.
First lookBlocking assignmentSituation: Let's look at this Code:
Always @ (posedge CLK)
Begin
Q1 = D;
Q2 = Q1;
Q3 = Q2;
End
The always statement block is sensitive to the rising edge of the CLK. When the CLK 0 ~ 1. Execute the always statement.
All statements in the begin... end statement block are executed sequentially.And the most important thing is that the blocking value assignment starts to execute the next statement after "right calculation" and "Left Update" are completed completely in this statement.
In this example, run q2 = Q1 after the value of D is assigned to Q1, and then run Q3 = Q2 after the value of Q2 is updated. In this way, the final calculation result is Q3 = D.
After all the statements are executed, the always statement waits for the rising edge of the CLK to trigger the begin... end statement again.
Next, let's take a look.Non-blocking assignment.
The so-called non-blocking value assignment, as the name suggests, means that the execution of the current statement will not block the execution of the next statement.
Always @ (posedge CLK)
Begin
Q1 <= D;
Q2 <= Q1;
Q3 <= Q2;
End
Run Q1 <= D,Generates an update event., Assign the current value of D to Q1,This assignment process is not executed immediately,Wait in the event queue.
Then run Q2 <= Q1 to generate an update event. The current Q1 value (note that the process of assigning the D value to Q1 in the previous statement is not completed, but Q1 is still the old one) assigned to Q2, this assignment event will also be in the waiting state in the event queue.
Run Q3 <= Q2 again to generate an update event, and assign the current Q2 value to Q3. This assignment event will also be waiting for execution in the event queue.
At this time, the always statement block is executed completely and starts to be sensitive to the rising edge of the next CLK.
So when will the three events waiting in the event queue be executed?Only when the currentSimulation timeAnd non-blocking update events. In this way, the values of D, Q1, and Q2 are assigned to Q1, q2, and Q3 at the same time.
Note:
* The simulator first sorts events according to the simulation time, and then sorts events in the current simulation time in the order of priority.
* Active events are events with the highest priority. Between Active events, their execution order is random. Blocking assignment (=), continuous assignment (assign), and right calculation of non-blocking assignment are all active events.
The following is a typical case to further illustrate the difference between blocking assignment and non-blocking assignment.
Here is an array: daTa [0], daTa [1], daTa [2] and DATa [3], all of which are 4-bit data. We need to find the smallest data among them andData IndexOutput to Min.AlgorithmIt is a bit similar to the "bubble sort" process, and needsCompleted within one clock cycle.For example, if daTa [2] is the minimum, so the min value is 2.
Module bubble_up (
Rst_n,
CLK,
Data,
Pai_min
);
Input rst_n;
Input CLK;
Input [3: 0] DATA [0: 3];
Output [1:0] pai_min;
Reg [1:0] pai_min;
Always @ (posedge CLK or negedge rst_n)
Begin
If (~ Rst_n)
Begin
Pai_min <= 2 'd0;
End
Else
Begin
If (data [0] <= data [1__min]) // "<=" indicates that the value is less than or equal
Begin
Optional _min <= 2 'd0; // "<=" indicates a non-blocking value.
End
If (data [1] <= data [minutes _min])
Begin
1__min <= 2 'd1;
End
If (data [2] <= data [minutes _min])
Begin
1__min <= 2' D2;
End
If (data [3] <= data [minutes _min])
Begin
Pai_min <= 2 'd3;
End
End
End
Endmodule
OurOriginal IntentionFirst, set pai_min to an initial value (any value is acceptable), and then set data [0] ~ Data [3] is compared with data [1__min]. For each comparison, a small index is saved in 1__min, and then the next comparison is performed. After the four groups of data are compared, the minimum data index will be retain_min.
We usedNon-blocking assignmentThe result shows that the simulation waveform is not what we need at all. The data in the Figure [0] ~ Data [3] is 11, 3, 10, and 12 respectively, and the initial value of pai_min is 0. In principle, the computation result of lid_min should be 1, because data [1] is the smallest, but the simulation waveform is 2.
Why does this happen?
When the rising edge of the clock arrives and the rst_n signal becomes invalid, execute the following four statements. Assume that the interval _min at this time is 0, data [0] ~ Data [3] is 11, 3, 10, and 12 respectively:
If (data [0] <= data [1__min]) // "<=" indicates that the value is less than or equal
Begin
Optional _min <= 2 'd0; // "<=" indicates a non-blocking value.
End
If (data [1] <= data [minutes _min])
Begin
1__min <= 2 'd1;
End
If (data [2] <= data [minutes _min])
Begin
1__min <= 2' D2;
End
If (data [3] <= data [minutes _min])
Begin
Pai_min <= 2 'd3;
End
The first sentence if isTrueTherefore, execute cmd_min <= 2 'd0. At this time, cmd_min andNot assigned immediately,The task is scheduled to wait for execution in the event queue, which is a non-blocking assignment feature.
The second sentence if isTrueTherefore, execute cmd_min <= 2 'd1. This is because cmd_min is not immediately assigned to 1, but is scheduled to the event queue for execution. The current interval _min is still 0, and no changes have occurred.
Similarly, if in the third sentence isTrueTherefore, execute cmd_min <= 2' D2 to schedule the update event to the event queue for execution. The current limit _min is still 0.
The if in the fourth sentence isFalseTherefore, skip pai_min <= 2' D3 directly, then jump out of the always statement and wait for the next rising edge of the clock.
After the preceding always statement is executed, the simulation time does not move forward.At this time, it exists on the current simulation time in the event queueThree scheduled non-blocking update eventsStart execution, and update cmd_min to 0, 1, and 2 respectively.
The three update events are events within the same simulation time according to the specifications of the Tilde language. The execution sequence between these events is random, which leads to uncertainty. Generally, the simulators are executed according to their scheduling order. The event queue is like a FIFO for storing events. It is part of the hierarchical event queue ,:
These three events are executed one by one during the same simulation time, and the last update event is actually active. Therefore, when the final result obtained during simulation, the limit _min is 2.
Then we want to get the result that after each if statement is judged and executed, the intermediate value will be saved in 1_min before the next comparison, that is, before the next comparison, this variable _ Min must be updated, which is also a feature of blocking assignment. Therefore, we will change the Code as follows:
Module bubble_up (
Rst_n,
CLK,
Data,
Pai_min
);
Input rst_n;
Input CLK;
Input [3: 0] DATA [0: 3];
Output [1:0] pai_min;
Reg [1:0] pai_min;
Always @ (posedge CLK or negedge rst_n)
Begin
If (~ Rst_n)
Begin
Pai_min <= 2 'd0;
End
Else
Begin
If (data [0] <= data [1__min]) // "<=" indicates that the value is less than or equal
Begin
Optional _min = 2 'd0; // "<=" indicates a non-blocking value.
End
If (data [1] <= data [minutes _min])
Begin
Pai_min = 2' D1;
End
If (data [2] <= data [minutes _min])
Begin
1__min = 2' D2;
End
If (data [3] <= data [minutes _min])
Begin
Pai_min = 2' D3;
End
End
End
Endmodule
Its simulation waveform:
In the Code simulation process, if the second sentence is true, execute pai_min = 2' D1, accordingFeatures of blocking assignment, 1__min is immediately assigned to 1. When the third sentence if is executed, if (data [2] <= data [1__min]) is false, skip _ min = 2' D2 and do not execute, similarly, skip pai_min = 2' D3 and do not execute it. When _ Min is finally assigned a value of 1, this is what we want.
In addition, to make the Code look more concise, we use the for statement to rewrite the Code:
Module bubble_up (
Rst_n,
CLK,
Data,
Pai_min
);
Input rst_n;
Input CLK;
Input [5: 0] DATA [0: 3];
Output [1:0] pai_min;
Reg [1:0] pai_min;
Integer I;
Always @ (posedge CLK or negedge rst_n)
Begin
If (~ Rst_n)
Begin
Pai_min = 2' D0;
End
Else
Begin
For (I = 2' D0; I <= 2' D3; I = I + 2' D1)
Begin
If (data [I] <= data [minutes _min])
Begin
Pai_min = I;
End
End
End
End
Endmodule
This method is completely equivalent to the preceding method and has the same functions. In the future, when reading the code, you will find it difficult to understand the circuit functions with for statements. You can expand these statements to enhance the readability of the Code.