## Ch4 Operator Gotchas
----
### 44. Assignment in expressions

* **Example and solution :**
```verilog=
if ( a = b ) ...// illegal in SystemVerilog
// solution
if ( (a = b) )...// legal in SystemVerilog
```
* **Conlusion :**
SystemVerilog's syntax is different from C's
----
### 45. Self-determined versus context-determined operators

* **Self-determined operators**
Without changing the size of the operand before operation.
* **Context-determined operators**
All operands need to expand to the largest vector size before operation.
----
* **Example :**
```verilog=
logic [5:0] a = 6'b101010;
logic [3:0] b = 4'b1111;
logic [7:0] c;
c = a | &b; // ans is 00101011
```
* **Step 1 : calculate &b.**
& is self-determined : And all bits of b(4'b1111) without changing size , then we get 1'b1.
* **Step 2 : calculate all statement**
| is context-determined : expand a and b to 8 bits , a = 8'b00101010 ; b = 8'b00000001.
* 關於 self/context-determined 可參考原文書 P102~P104 Table
----
### 46. Operation size and sign extention in assignment statements

* **Zero-extend**
==Any== operand or self-determined operation result on the ==right-hand side== of the assignment is ==unsigned== , then the smaller vectors are left extended with zeros.
----
* **Sign-extend**
==All== operand or self-determined operation result on the ==right-hand side== of the assignment are ==signed== , then the smaller vectors are left extended using sign extention.
----
* **Example and solution :**
```verilog=
logic [3:0] u1,u2;
logic signed [3:0] s1,s2;
logic [7:0] u3;
logic signed [7:0] s3;
// Example
s3 = u1 + u2; // zero extension
u3 = s1 + s2; // sign extention
s3 += 2'b11; // zero extension
// solution
s3 = s1 + signed'(u2);
```
----
### 47. Signed arithmetic rules

* **Example and solution :**
```verilog=
module signed_adder_no_carry_in
(input logic signed [3:0] a, b,
input logic cin,
output logic signed [3:0] sum,
output logic cout);
assign {cout,sum} = a + b + cin; // GOTCHA!! unsigned 5-bit adder
assign {cout,sum} = a + b + signed'(cin); // GOTCHA!! signed'(ci) = 5'b11111 = -1
// solution
assign {cout,sum} = a + b + signed'({1'b0,cin});
endmodule
```
----
### 48. Bit-select and part-select operations

* **Part select operation is always unsigned , even when the entire vector is selected.**
----
* **Example and solution :**
```verilog=
logic signed [31:0] a, b;
logic signed [31:0] sum1;
logic signed [7:0] sum2;
assign sum1 = a[31:0] + b[31:0]; // GOTCHA!! unsigned adder
assign sum2 = {a[31],a[6:0]} + {b[31],b[6:0]} // GOTCHA!! unsigned adder
// solution
assign sum3 = signed'({a[31],a[6:0]}) + signed'({b[31],b[6:0]});
```
----
### 49. Increment,decrement and assignment operators

```verilog=
always_ff @(posedge clk, negedge reset_n)
if (reset_n) fifo_write_ptr = 0;
else if (!fifo_full) fifo_write_ptr++;
always_ff @(posedge clk)
if(fifo_write_ptr == 15) fifo_full <=1;// GOTCHA!!
else fifo_full <=0;
```
----
* **++ operator performs a blocking assignment , so value update can occur before or after the second block has sampled the value.** ( 會發生兩種情況 )
* **Solution :**
```verilog=
always_ff @(posedge clk, negedge reset_n)
if (reset_n) fifo_write_ptr = 0;
else if (!fifo_full) fifo_write_ptr <= fifo_write_ptr + 1;// use nonblocking assignment
always_ff @(posedge clk)
if(fifo_write_ptr == 15) fifo_full <=1;
else fifo_full <=0;
```
----
### 50. Pre-increment versus post-increment operations

* **Example :**
```verilog=
integer i=16;
while(i--)... ; // test i , then decrement.loop will execute 16 times
while(--i)... ;// decrement i , then test.loop will execute 15 times
```
----
### 51. Modifying a variable multiple times in one statement

* **Example and solution :**
```verilog=
integer i = 10 , j;
j = --i + ++i;// GOTCHA!! multiple operation on same variable;
// solution
integer temp = --i;
j = temp + i++;// add temp and i,then increment i
```
----
### 52. Operators evaluation short circuiting

* **Example :**
```verilog=
always @(posedge clock)
if ( f(il,ol) && f(i2,o2) )// GOTCHA!! possible side effects
mem[addr] <= data_in;
function f(input [7:0] d_in, output [7:0] d_out);
d_out = d_in + 1;
if (d_out == 255) return 0;
else return 1;
endfunction
```
----
* **Why GOTCHA happen?**
In software,logical AND operation is evaluated from left to right.
If return value of the first function is 0 , the result of the AND operation is known
without having to evaluate the second function.
So the second function is not called , and its value is not updated.
----
* **Soluion :**
```verilog=
always @(posedge clock) begin
temp1 = f(i1,o1); // o1 will be updated every time
temp2 = f(i2,o2); // o2 will be updated every time
if ( templ && temp2 ) // OK! no side effects
mem[addr] <= data in;
end
```
----
### 53. The not operator(!) versus the invert opertor(~)

* **Not : logical operator**
perform a true/false test first and then inverts the 1-bit tese result.
* **Invert : bitwise operator**
inverts the value of each bit of a vector.
* **Not and invert is the same only for 1-bit values.**
----
* **Example :**
```verilog=
logic a;
logic [1:0] b;
a = 1;
b = 1; // 2'b01;
// !a = 0
// ~a = 0
// !b = 0
// ~b = 2'b10
```
----
### 54. Array method operations

* **Example :**
```verilog=
logic [7:0] fifties [0:3] = '{50,100,150,200}; // 8-bit array
$display("fifties.sum is %0d", fifties.sum); /* GOTCHA!sums up 50 + 100 + 150 + 200 and
returns the clearlyincorrect totalof 244 */
```
----
* **Why GOTCHA happen?**
.sum is context-determined , and each member of the array is 8-bits wide,
then result is 8-bits size , if overflow , the value will be truncated , and leave 8-bits.
----
* **Soluion :**
```verilog=
// solution1
$display ("fifties. sum is %0d", (fifties. sum + 16'd0) ) ;// extend to 16-bits wide
//solution2
int total;// 32-bit integer variable
total = fifties.sum
$display("total is %0d", total);
```
----
### 55. Array method operations on an array subset

* **Example :**
```verilog=
program automatic test;
initial begin
int count, a[] = '{9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
count = a.sum with (item> 7);// GOTCHA: expect 17, get 2
$display("\"a.sum with(item > 7)\" returns %0d", count);
end
endprogram
```
----
* **Why GOTCHA happen?**
(item > 7) is a true/false expression , and return value is 1'b1 or 1'b0
The sum of return value = 2 (9 > 7 and 8 > 7)
* **Soluion :**
```verilog=
//solution1
count a.sum with( (item> 7) ? item: 0 );
//solution2
count a.sum with( (item> 7) * item );
```
---
## Ch5 General Programming Gotchas
----
### 56.Verifying asynchronous correctly reset at time zero

* A gotcha is not understanding to schedule initial and always blocks
----
* **Example for asynchronous**
```verilog=
module chip(input logic clock, input logic reset_n);
always_ff @(posedge clock, negedge reset_n) //Asynchronous reset
if(!reset_n) q <= 0;
else q <= d;
end module
module test(input logic clock, output logic reset_n);
initial begin
reset_n = 0; //Gotcha! activating at time zero
#10 reset_n = 1;
end
endmodule;
module top();
initial begin
clock = 0;
forever #5 clock = ~clock; //OK,rising clk at time 5
end
endmodule
```
----
* **Why this Gotcha happens?**
* We hope always_ff procedural block be activated first, then encouter @timing control to wait for negtive edge of reset_n.
* But initial and always procedural blocks become active at time zero that we CANNOT guarantee which will run fast.
* It may make always_ff miss the negative edge of reset_n.
----
* **Solution**
use nonblocking assignment to delay the reset_n in the initial block
```verilog=
module test(input logic clock, output logic reset_n);
initial begin
reset_n <= 0; //reset activated after delta time
#10 reset_n = 1;
end
endmodule;
module top();
initial begin
clock <= 1; //rising clock after delta time
forever #5 clock = ~clock;
end
endmodule
```
----
* **Example for synchronous**
```verilog=
module chip(input logic clock, input logic reset_n);
always_ff @(posedge clock)//Synchronous reset
if(!reset_n) q <= 0;
else q <= d;
end module
module test(input logic clock, output logic reset_n);
initial begin
reset_n = 0;
#10 reset_n = 1;
end
endmodule;
module top();
initial begin
clock = 1; //Gotcha! Rising clock edge at time zero
forever #5 clock = ~clock;
end
endmodule
```
----
* **Solution**
```verilog=
module test(input logic clock, output logic reset_n);
initial begin
reset_n = 0; //reset before delta
#10 reset_n = 1;
end
endmodule;
module top();
initial begin
clock <= 1; //rising clock after delta
forever #5 clock = ~clock;
end
endmodule
```
----
* **Solution using SystemVeilog for Asynchronous**
Program block is scheduled to take place after blocking or nonblocking in the module block
```verilog=
program automatic test (input logic clock, output logic reset_n);
initial begin
reset_n <= 0; // OK, reset activated as verification event
#10 reset n <= 1;
end
endprogram
module top;
initial begin
clock <= 1; // OK, first rising clock after delta
forever #5 clock = ~clock;
end
endmodule
```
----
### 57.Nested if...else blocks

If else branch is optional, it leads to the confusion when if...else are nested within other if..else
* **Example**
```verilog=
if (a >= 5)
if (a <= 10)
$display (" 'a' is between 5 and 10");
else
$display(" 'a' is less than 5");//Gotcha, pairs with wrong if
```
----
* **Why Gotcha happens?**
An else statement is altomatically associated with the nearest ==if== statement that doesn't have ==else==.
* **Solution**
use ==begin...end== to show which statements belong to the if branch
```verilog=
if (a >= 5)begin
if ( a<=10 )
$display (" 'a' is between 5 and 10");
end
else
$display(" 'a' is less than 5");
```
----
### 58.Evalution of equality wuth 4-state values

* **Example**
```verilog=
alway @(posedge test_clock)
if(data != expect) //Gotcha!
$display("Error on data:saw %h, expected %h",data,expected);
```
----
* **Why is Gotcha?**
If the expression is evaluated as either false or ==unknown==, the *else* branch is taken.
* The equality/inequality operators handle 4-state values.
If the two operands are equivalent, the operation result is ==true==. ->1b'1
If the two operands are different, the operation result is ==false==. ->1b'0
If the either operands is unknown, the operation result is ==unknown==. ->1b'x
----
* **Solution**
Using identity operator(=== or !==) to perform a bit-to-bit comparison of the two operands.
```verilog=
alway @(posedge test_clock)
if(data !== expect) //Gotcha!
$display("Error on data:saw %h, expected %h",data,expected);
```
----
### 59.Event trigger race conditions

* Event data type, including ==->== event trigger operator, and ==@== event timing control. It is used to signal the completion of one block and enabling the other.
----
* **Example**
```verilog=
module event_example_1;
event get_data, send_data;
initial -> get_data; //Gotcha! trigger at time zero
always @(get_data) begin
->send_data;
end
always @(send_data) begin
->get_data;
end
endmodule;
```
* **Why gotcha happens?**
If the initial block avtivates and executes before the always @(get_data) block activates, the sequence will never start.
----
* **Solution using Verilog**
>To delay the trigger in the initial block.
```verilog=
initial #0 -> get_data; //delay trigger
/*#0 delay will hold off triggering the get_data event until
all procedure blocks have been activated.*/
```
----
* **Solution using SystemVerilog**
>Use ==->>== to triger afer delta time.
```verilog=
initial ->> get_data; //tigger after delta
```
>Use a trigger persistence property
```verilog=
intitial -> get_data;
always begin
wait(get_data.triggered) //doesn't matter that the
->sned_data; //trigger occur before or after
end
```
----
### 60.Using semaphores for synchronization

* SystemVerilog provides two mechanisms, which are ==semaphores== and ==mailbox==, are more flexible and versatile than event trigger.
* Semaphores are like a bucket that can hold a number of keys or tokens.
----
* **Example**
```verilog=
semaphore s_test = new;//create a semaphore bucket
initial begin: Block1
s_test.put(5);
s_test.get(3);
s_test.get(4); //get(4)cannot be serviced,
//the request is put into FIFO
end: Block1
initial begin: Block2 #10 //At time 10
s_test.get(2) /* Gotcha!,even through get(4) is in FIFO,
get(2) will be serviced first
```
----
* **Why gotcha happens?**
If more than one key is requestes, and that number is not available, the requset is put into FIFO(First in, First out), and wait until the requested number is available.
However, the Gotcha is that each time get() is called, and attempt is made to retrieve the requested number, even if other requests are waiting in FIFO.
* **Solution**
```verilog=
repeat(3) s_test.get(1);
//use get(1) multiple times, instead of get(x) once
```
----
### 61.Using mailboxes for synchronization

When messages are retrived from the mailbox with get(), the receiving variable must be the same data type as the value placed in the mailbox.
----
* **Example**
```verilog=
logic [15:0] a,b;
int i,j,s;
mailbox mbox1 = new;
initial begin
mbox1.put(a);
mbox1.put(i);
mbox1.get(b);
mbox1.get(b);//Error! b is wrong type for the second message
```
----
* **Solution**
1. Use try_get() and returs status flag.
* Return 0 if there is no message.
* Return 1 if receiving variable is type-compatible, and message is retrived.
* Return a negative value if receiving variable is type-incompatible, and message is not retrived.
```verilog=
s = mbox1.try_get(d_out);
case(s)
1: $display("try_get() succeeded");
0: $display("try_get() failed, no message in mailbox");
default: $display("try_get () failed due to type error");
endcase
```
----
2. Use typed mailbox
```verilog=
typedef struct {int a, b} data_packet_t;
mailbox #(data-packet_t) mbox2 = new;
```
----
### 62.Triggering on clocking blocks

* **Example**
```verilog=
program automatic test (input logic clk,
input logic grant,
output logic request);
clocking cb @(posedge clk);
output request;
input grant;
endclocking
initial begin
@(posedge cb) //GOTCHA!: cannot select edge of clocking block
$display("At %Od: clocking block triggered", $time);
end
endprogram
```
----
* **Why Gothcha happens?**
@ event control to delay until a clocking block clock occur should NOT specify posedge or negedge of the clocking block name.
The test program doesn't need to know if the interface uses posedge, negedge, or both.
* **Solution**
```verilog=
initial begin
@(cb) // OK: delay until clocking block event occurs
$display("At %Od: clocking block triggered", $time);
end
```
----
### 63. Misplaced semicolons after decision statements

* **Example :**
```verilog=
module foo;
reg a;
initial begin
a = 1;
if (a); // semicolon is wrong, but NOT syntax error
$display("'a' is true"); // GOTCHA! also prints when 'a'
// is false
end
endmodule
```
```verilog=
module bar;
reg a;
initial begin
a = 1;
if (a); // semicolon is NOT an error
$display("'a' is true");
else // SYNTAX ERROR! 'else' does not
// follow 'if'
$display("'a' is false");
end
endmodule
```
* **How to avoid this Gotcha :**
Remove the semicolons.
----
### 64. Misplaced semicolons in for loops

* **Example :**
```verilog=
module foo;
integer i;
initial begin
for (i=O; i<=15; i=i+l); // semicolon is NOT an error
begin
$display("Loop pass executing"); // GOTCHA! only executes once
end
end
endmodule
```
* **How to avoid this Gotcha :**
Remove the semicolons.
----
### 65. Infinite for loops

* **Example :**
```verilog=
reg [3: 0] i; // 4-bit loop control variable
for (i=O; i<=lS; i=i+l) // GOTCHA! i<=15 is always true
begin 1* loop body *1 end
```
> As a 4-bit variable, when i has a value of 15 and is incremented, the result is 0, which is less than or equal to 15.
* **How to avoid this Gotcha :**
1. Increase the size of the loop control variable so that it can hold a larger value.
2. Typically, either integer (a Verilog type) or int (a SystemVerilog type) should be used as loop control variables, both of which are 32-bitsigned variables.
```verilog=
reg [3:0] result; // 4-bit design or test variable
for (int i=O; i<=15; i=i+l) // OK, i can have a value greater than 15
@(posedge elk) result = i; // OK, but mismatch in assignment sizes
```
----
### 66. Locked simulation due to concurrent for loops

Parallelfor loops that use the same control variable can interfere with each other.
* **Example :**
```verilog=
program automatic test;
logic [7:0] a, b, c, sum, dif;
int i; // GOTCHA! shared loop variable
adder subtractor dut (.*);
initial begin
fork
begin: add_test
for (i = 0; i < 10; i++) begin // increment i
a = i;
b = i + 10;
#10 $display("At %Od, in scope %m: i=%Od sum=%Od", $time, i, sum);
end
end
begin: dif_test
for (i = 8; i > 2; i--) begin // decrement i
c = i;
#10 $display("At %Od, in scope %m: i=%Od dif=%Od", $time, i, dif);
end
end
join
$display("\nTests finished at time %Od\n", $time);
$finish;
end
endmodule
```
* **How to avoid this Gotcha :**
1. Use different variables for each loop.
2. Use the SystemVerilog feature of declaring a local variable as part of each for loop.
```verilog=
initial begin
fork
begin: add_test
for (int i = 0; i < 10; i++) begin // i is local variable
end
end
begin: dif_test
for (int i = 8; i > 2; i--) begin // i is local variable
end
end
join
```
----
### 67. Referencing for loop control variables

Verilog requires that loop control variables be declared before the variable is used in a for loop.
-> It is a static variable that can alsobe used outside the for loop.
* **Example :**
```verilog=
reg [31:0] a, b, c:
integer a[0:31], b[0:31], c[0:31]; // arrays of 32 elements
integer i; // static loop control variable
initial begin
for (i=O; i<=31; i=i+l) begin
c[i] = a[i] + b[i]; // OK to reference i inside of loop
end
$display (" i is %Od", i) // OK to reference i outside of loop
end
```
SystemVerilog allows declaring for loop control variables within the declaration of the loop.
-> It is illegal to reference the variable outside of the scope in which it exists.
* **Example :**
```verilog=
reg [31:0] a, b, c;
initial begin
for (int i=O; i<=31; i=i+1) begin // i is automatic variable
c[i] = a[i] + b(i]; // OK, i is used inside the loop
end
$display (" i is %Od", i); // GOTCHA! i is used outside of loop
end
```
* **How to avoid this Gotcha :**
The loop variable should be declared outside of the loop.
----
### 68. Default function return size

Verilog functions have a default return type of 1-bit logic, if no return type is specified.
* **Example :**
```verilog=
module test;
int result; // 32-bit variables
function sum (int a, b); // no return size specified
return (a + b);
endfunction
initial begin
result = sum(3,4); // GOTCHA! 32-bit result is always 0 or 1
$display("sum(3,4) return = %h (hex)", result);
end
endmodule: test
```
* **How to avoid this Gotcha :**
An explicit return size or type needs to be specified. A good coding guideline would be to always specify the function return type, even when a 1-bit return is desired.
----
### 69. Task/function arguments with default values

The formal arguments of a task or function can be input, output, inout, or ref.
In SystemVerilog, task/function arguments default to **input** if no direction has been specified, and the direction is sticky, so that, once it has been specified, **it affects all subsequent arguments** until a new direction is specified.
SystemVerilog allows input and inout arguments of a task or function to be specified with a default value.
* **Example :**
```verilog=
function automatic int array_sum(ref int all, int start=O);
for (int i=start; i<a.size(); i++) // Gotcha! start has a default value specified.
array_sum += a[i));
endfunction
```
* **How to avoid this Gotcha :**
Specify a direction for all task/function arguments.
```verilog=
function int array_sum(ref int a[], input int start=O);
```
----
### 70. Continuous assignments with delays cancel glitches

Continuous assignment statements are continuously running processes that transfer an expression from the right-hand side to a net or variable on the left-hand side.
In a synthesizable RTL model, continuous assignments are typically written to use zero delay.
In a testbench or bus-functional model, it is sometimes desirable to add a propagation delay between the right-hand expression change and when the left-hand side net or variable is updated.
* **Example :**
```verilog=
module clock_gen;
timeunit Ins; timeprecision Ins;
logic clockO, clock3, clock6;
initial begin
clockO <= 0;
forever #5 clockO = ~clockO;
end
assign #3 clock3 = clockO; // OK, clock3 works as expected
assign #6 clock6 = clockO; // GOTCHA! clock6 flat lines
initial begin
$time forma t (- 9 , 0, " n5", 7);
$monitor("%t: clockO = %b clock3 = %b clock6 %b", $time, clockO, clock3, clock6);
#30 $finish;
end
endmodule: clock_gen
```
Continuous assign statements use an *inertial delay mechanism* to propagate value changes, each scheduled change cancels any earlier scheduled changes that have not yet occurred.
* **How to avoid this Gotcha :**
Using a *transport delay mechanism*, instead of *inertial delay mechanism*.
-> Use an always procedural block with a nonblocking intra-assignment delay.
```verilog=
always @(clockO)
clock6 <= #6 clockO; // OK, 6ns intra-assignment delay
```
{"title":"Gotchas_101 : Stuart Ch4 & Ch5","contributors":"[{\"id\":\"4894c85e-8918-49e6-9ca5-419dd41e3610\",\"add\":24009,\"del\":64},{\"id\":\"2d84cbbf-f82f-42fd-bec7-04d4d140cded\",\"add\":102,\"del\":96},{\"id\":\"ee23e0f6-70ad-4e5b-8767-0ae681b4f453\",\"add\":96,\"del\":56}]"}