SystemVerilog: Evaluating expressions

Apologies for the late post. Today I will like to describe about the technique used for evaluation of various simple-looking expressions in SV. Reading from System Verilog LRM 1800-2012, Chapter 11, following is the definition of expression:

An expression is a construct that combines operands with operators to produce a result that is a function of the values of the operands and the semantic meaning of the operator. Any legal operand, such as a net bitselect, without any operator is considered an expression.

Operand can be a variable, constant or anything from n-number of available resources.
Operators are the symbols used to perform mathematical or logical operations on the operands.

Operators may be applied to 2-state values or 4-state values or to a mixture of 2-state and 4-state values. The result is the same as if all values were treated as 4-state values. If all the operands are 2-state, then the result is optimized to 2-state value.

For example, the X’s in following expression is optimized to 0 automatically since int is a 2-state datatype:

int n = 8'b0010_xxxx | 4'b0101_1010; // n evaluates to 8'b0011_1010. 'x gets optimized to Zero
integer m = 'h4/0; // m evaluates to 'x. Division by Zero.

SystemVerilog uses the bit length of the operands to find out that how many bits to be used while evaluating an expression. The bit length of LHS variable matters the most. The bit length rules are given in 1800-2012 Section 11.6.1. In the case of the addition operator, the bit length of the largest operand, including the left-hand side of an assignment, shall be used. Following is an example from LRM about that will clear out the bit length understanding:

logic[15:0] a, b; // 16-bit variables
logic [15:0] sumA; // 16-bit variable
logic [16:0] sumB; // 17-bit variable
sumA = a + b; // expression evaluates using 16 bits
sumB = a + b; // expression evaluates using 17 bits

The simple looking arithmetic can pose many problems as described in the following example:

logic[7:0] a, b, answer; // 7-bit variables

answer = (a + b) >> 1; // incorrect functioning

answer = (a + b + 0) >> 1; // correct functioning

Here, all the variables are 8 bits. “a” and “b” are added and right-shifted by 1 to preserve the carry bit. But, there the expression (a+b) will be evaluated for 8 bits only and the overflow bit will be lost. When shifting by 1, it will just append a 0 on the MSB side (and not the actual overflow bit).

A solution to this will be to make this expression of 32 bits length. Note that adding a “0” to (a+b) will take “0” as a 32 bit integer value and perform the addition for 32 bits. Henceforth the overflow bit can be correctly preserved now.

Let’s take a simple used example about how badly we need these things. Just try to answer the output of following code by yourself and then look at the answers:

bit [7:0] test = 255;
if(test == 255) $display("1. test is 255"); else $display("1. test is not 255");
if(test == '1) $display("2. test is '1"); else $display("2. test is not '1");
$display("3. ~test = %b",~test);
if(~test == 0) $display("4. test is 0"); else $display("4. test is not 0");
if(~test == '0) $display("5. test is '0"); else $display("5. test is not '0");

   // OUTPUT

  1. test is 255
  2. test is ‘1
  3. ~test = 00000000
  4. test is not 0
  5. test is ‘0

I think the most confusing will be 4th one. Here, “0“, without any width prefix defaults to 32-bit value as discussed in the previous example. So, test will expand to 32 bits and now test will be “32’h0FF“, then inverting it making ~test=32’h100 and then comparing it to 32’h0. This will obviously fail in the equality check.

Note that in an equality expression, the operands get sized to the maximum width between the expressions on the LHS and RHS expressions before evaluating those expressions.

If we use ~test==9’h100 and then it will work fine since now the expression is of 9-bits. Also, will work since we are evaluating the expression for 8-bits only.

Reference for the above example: Stackoverflow: How is SystemVerilog 0 different from ‘0.

Hope this helps in avoiding minor and confusing mistakes while coding expressions for different lengths in System Verilog. For detailed information about expression evaluation rules, refer to Section 11.8 of LRM 1800-2012.

One response

  1. Cheers! Will have to go through that again.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: