## Ch4 Operator Gotchas ---- ### 44. Assignment in expressions ![](https://hackmd.io/_uploads/SJwLxVG52.png) * **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 ![](https://hackmd.io/_uploads/H18QUNf92.png) * **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 ![](https://hackmd.io/_uploads/rktykrGc2.png) * **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 ![](https://hackmd.io/_uploads/SyNmNLGc2.png) * **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 ![](https://hackmd.io/_uploads/SkrbdLzq3.png) * **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 ![](https://hackmd.io/_uploads/r18tiLMq3.png) ```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 ![](https://hackmd.io/_uploads/HJDqR8Mq3.png) * **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 ![](https://hackmd.io/_uploads/B1fSkDMcn.png) * **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 ![](https://hackmd.io/_uploads/HyAylDf9n.png) * **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(~) ![](https://hackmd.io/_uploads/rytglPfcn.png) * **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 ![](https://hackmd.io/_uploads/B1UZlDfc3.png) * **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 ![](https://hackmd.io/_uploads/B19ExDfq2.png) * **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 ![](https://hackmd.io/_uploads/rJ0VC_zq2.png) * 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 ![](https://hackmd.io/_uploads/S1qzt2M5n.png) 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 ![](https://hackmd.io/_uploads/Skh_62M93.png) * **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 ![](https://hackmd.io/_uploads/r1f3A3Q9h.png) * 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 ![](https://hackmd.io/_uploads/rJt7YpQcn.png) * 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 ![](https://hackmd.io/_uploads/BJUhJC7ch.png) 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 ![](https://hackmd.io/_uploads/rkkqPA75n.png) * **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 ![](https://hackmd.io/_uploads/Skp6pjQ53.png) * **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 ![](https://hackmd.io/_uploads/HkY10iXcn.png) * **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 ![](https://hackmd.io/_uploads/BkWbCjX5n.png) * **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 ![](https://hackmd.io/_uploads/S1Pf0s7ch.png) 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 ![](https://hackmd.io/_uploads/rJBUCjXq3.png) 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 ![](https://hackmd.io/_uploads/BkuPAi752.png) 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 ![](https://hackmd.io/_uploads/rk2OAjXch.png) 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 ![](https://hackmd.io/_uploads/SJW50s7c3.png) 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}]"}
    149 views
   Owned this note