Why Should We Never Use Self-Determined Expressions in RTL?

A self-determined expression is the one whose bit length is solely determined by the expression itself.

SystemVerilog LRM defines the bit lengths resulting from self-determined expressions. In the table below, i, j, and k represent expressions of an operand, while L(i) represents the operand i’s bit width.

Bit lengths resulting from self-determined expressions from SystemVerilog LRM

Designers should avoid using self-determined expressions in RTL, since self-determined expressions may lose carry bits.

SystemVerilog LRM has an example of how this can happen:

logic [15:0] a, b, answer;
assign answer = (a + b) >> 1;

The intention is to add “a” and “b” (resulting in an overflow), and then do a right shift by 1 to preserve the carry bit in the 16-bit “answer”. However, all operands in this self-determined expression are 16-bit in width, thus the expression (a + b) produces an intermediate result of 16 bits, and the carry bit is lost during the right shift operation.

The best practice is to make the widths of expression (a + b) explicit by using an intermediate variable to hold the results of this expression.

The following are some other examples where self-determine expressions can create unintended results:

// DO NOT do this!
z = (a + b) > c;
if ((a + b) > c) …

// DO this instead!
x = a + b;
z = x > c;
if (x > c) …

Reference:

  1. SystemVerilog LRM: https://fpga.mit.edu/6205/_static/F23/documentation/1800-2017.pdf

Subscribe

Enter your email to get updates from us. You might need to check the spam folder for the confirmation email.

Leave a comment