What is a gotcha?
A gotcha is code that looks right, feels right, and smells right ... but isn‘t. If you‘re lucky, it won‘t pass compilation, so that you‘ll know immediately that something is wrong. If you‘re less lucky, it will do something obviously wrong in simulation, like getting stuck in reset. If you‘re really unlucky, it will pass compilation and simulate, but with a subtle error that you‘ll be hard pressed to detect. And in the worst case, it will cause a bug in silicon
GOTCHA Number-01:
This gotcha is already appear in Verilog (1995 or 2001) and are still in SystemVerilog :-)
always @* oscillations (V2K1)
For coding synthesizable RTL in Verilog-2001, we usually recommend to code combinational and latch blocks with always @* and its automatic sensitivity list instead of manually enumerating the sensitivity list in a regular always procedure.
However, there is a case where that can get you into trouble.
Suppose you have two always @* procedures containing for-loops and you use the same loop index variable for both, like this:
integer k; reg [31:0] out1[0:7], out2[0:15], in1, in2;
always @* for (k = 0; k <8; k = k+1) out1[k] = in1 + k ; always @* for (k = 0; k <16; k = k+1) out2[k] = in2 * k ; Why not? In Verilog-1995, we used the same loop index with multiple loops all the time for RTL without problems. Suddenly, in V2K1 (Verilog2001), they find that some simulators get stucked. All they did was change the sensitivity list to @*. Darn those language developers! Can‘t they leave well enough alone?? :-) What happens here is that according to the LRM of V2K1, the first always @* turns into "always @(in1 or k)" and the second turns into "always @(in2 or k)". Note that k appears in both lists. Suppose that in1 changes. This triggers the first always @* procedure. It executes, including the loop, and k changes a number of times. k changes, you said? That triggers the second procedure, even though in2 has not changed. The second procedure executes unnecessarily, wasting simulator time, but that is not the worst of it. When the second procedure executes, it also executes its for-loop, also changing k. This retriggers the first procedure. And so they go on, back and forth, with the simulator stuck in an infinite loop. GOTCHA! Why did this not happen in Verilog-1995? Because then we did not put the loop index into the manual sensitivity list. But in always @*, it is put in automatically. (This problem does not occur with all simulators. Apparently some of them don‘t put the loop index into the sensitivity list even though strict compliance to the LRM would do so.) How can we fix this ? (Solution to avoide this gotcha): Solution 01: We have to use different variables for each of the loops. We can declare two different variables globally, like this: integer k1, k2; reg [31:0] out1[0:7], out2[0:15], in1, in2; always @* for (k1 = 0; k1 <>out1[k1] = in1 + k1 ;
always @* for (k2 = 0; k2 <>out2[k2] = in2 * k2 ;
Solution 02 :
Another way is to declare the loop variables locally within the always @* procedures, like this:
reg [31:0] out1[0:7], out2[0:15], in1, in2;
always @*
begin:loop1
integer k;
for (k = 0; k < k =8; k= k+1) out1[k] = in1 + k ; end always @* begin:loop2 integer k; for (k = 0; k < 16; k = k+1) out2[k] = in2 * k ; end Solution if you are using SystemVerilog: If we can use SystemVerilog, then we can change the always @* to always_comb, which will not put in the sensitivity list any variable that is written to within the procedure. Another solution in SystemVerilog is to declare the loop variables within the for-statement itself, like this: for (int k = 0; k <>
This also makes each loop variable separate. This is the best solution, as using the same variable for the different loops is what caused the problem in the first place.
"Gotcha number 01 was over here, hope you have got the idea on this gotcha and now onwards keep in mind while coding"
Please feel free to discusse this gothcha if you have any question or doubt on ankitgopani83@gmail.com
A gotcha is code that looks right, feels right, and smells right ... but isn‘t. If you‘re lucky, it won‘t pass compilation, so that you‘ll know immediately that something is wrong. If you‘re less lucky, it will do something obviously wrong in simulation, like getting stuck in reset. If you‘re really unlucky, it will pass compilation and simulate, but with a subtle error that you‘ll be hard pressed to detect. And in the worst case, it will cause a bug in silicon
GOTCHA Number-01:
This gotcha is already appear in Verilog (1995 or 2001) and are still in SystemVerilog :-)
always @* oscillations (V2K1)
For coding synthesizable RTL in Verilog-2001, we usually recommend to code combinational and latch blocks with always @* and its automatic sensitivity list instead of manually enumerating the sensitivity list in a regular always procedure.
However, there is a case where that can get you into trouble.
Suppose you have two always @* procedures containing for-loops and you use the same loop index variable for both, like this:
integer k; reg [31:0] out1[0:7], out2[0:15], in1, in2;
always @* for (k = 0; k <8; k = k+1) out1[k] = in1 + k ; always @* for (k = 0; k <16; k = k+1) out2[k] = in2 * k ; Why not? In Verilog-1995, we used the same loop index with multiple loops all the time for RTL without problems. Suddenly, in V2K1 (Verilog2001), they find that some simulators get stucked. All they did was change the sensitivity list to @*. Darn those language developers! Can‘t they leave well enough alone?? :-) What happens here is that according to the LRM of V2K1, the first always @* turns into "always @(in1 or k)" and the second turns into "always @(in2 or k)". Note that k appears in both lists. Suppose that in1 changes. This triggers the first always @* procedure. It executes, including the loop, and k changes a number of times. k changes, you said? That triggers the second procedure, even though in2 has not changed. The second procedure executes unnecessarily, wasting simulator time, but that is not the worst of it. When the second procedure executes, it also executes its for-loop, also changing k. This retriggers the first procedure. And so they go on, back and forth, with the simulator stuck in an infinite loop. GOTCHA! Why did this not happen in Verilog-1995? Because then we did not put the loop index into the manual sensitivity list. But in always @*, it is put in automatically. (This problem does not occur with all simulators. Apparently some of them don‘t put the loop index into the sensitivity list even though strict compliance to the LRM would do so.) How can we fix this ? (Solution to avoide this gotcha): Solution 01: We have to use different variables for each of the loops. We can declare two different variables globally, like this: integer k1, k2; reg [31:0] out1[0:7], out2[0:15], in1, in2; always @* for (k1 = 0; k1 <>out1[k1] = in1 + k1 ;
always @* for (k2 = 0; k2 <>out2[k2] = in2 * k2 ;
Solution 02 :
Another way is to declare the loop variables locally within the always @* procedures, like this:
reg [31:0] out1[0:7], out2[0:15], in1, in2;
always @*
begin:loop1
integer k;
for (k = 0; k < k =8; k= k+1) out1[k] = in1 + k ; end always @* begin:loop2 integer k; for (k = 0; k < 16; k = k+1) out2[k] = in2 * k ; end Solution if you are using SystemVerilog: If we can use SystemVerilog, then we can change the always @* to always_comb, which will not put in the sensitivity list any variable that is written to within the procedure. Another solution in SystemVerilog is to declare the loop variables within the for-statement itself, like this: for (int k = 0; k <>
This also makes each loop variable separate. This is the best solution, as using the same variable for the different loops is what caused the problem in the first place.
"Gotcha number 01 was over here, hope you have got the idea on this gotcha and now onwards keep in mind while coding"
Please feel free to discusse this gothcha if you have any question or doubt on ankitgopani83@gmail.com

0 comments:
Post a Comment