Jim Foley, Director of R&D, Real Intent
Jim Foley, prior to his role as R&D Director at Real Intent, was Head for Power Analysis Products at Sequence Design, and has held product management and development roles at Cadence Design Systems. Jim received a BS in Electrical Engineering from Worcester Polytechnic Institute. Go Engineers!
Ascent Lint Rule of the Month: ARITH_CONTEXT
February 7th, 2013 by Jim Foley, Director of R&D, Real Intent
Quick, what’s two plus two? The answer is four, of course, assuming you have enough bits to compute the entire result. When writing code in Verilog, this is not always a safe assumption.
In Verilog, each expression is determined to have a specific bit length. For the logic expressions (e.g. and, or, xor) and arithmetic expressions (e.g. add, subtract, multiply), if the expression is on the right-hand-side of an assignment, then the length is determined by the size of the result on the left-hand-side. If the expression isn’t in an assignment, or appears in a concatenate or index range, then its length is determined by its largest argument. Literal integers, specified without a length, are 32 bits long.
For example, in the assignment:
qq[2:0] = aa[1:0] + bb[1:0]
The assignment is to a three-bit value, so the add operation of aa and bb is determined to be three bits wide. But in the statement:
$display(“This value is %x”, mem[ aa[1:0] + bb[1:0] ]);
the add operation here is two bits long, as it’s largest operand is two bits. If aa and bb are both 2’d2, then the carry bit is discarded and the result of the add here is 2’d0. (The details of how expression lengths are determined are spelled out in the Verilog Language Reference Manual, IEEE-1364.)
This may or may not be what you expect. Sometimes dropping the carry bit and having an arithmetic operation wrap around back to zero is what you intend, and sometimes it isn’t. The lint rule ARITH_CONTEXT will let you know when you have an arithmetic expression in a context where its length is self-determined, which may cause high-order bits to be dropped from the result.
Note that if you include a literal integer in the mix:
$display(“The other value is %x”, mem[aa[1:0] + 2]);
the add itself is 32 bits. If aa is still 2, then two plus two equals four again. The ARITH_CONTEXT rule expects that if you’re doing math with integers, then 32 bit precision is enough for whatever calculation you’re doing, so you don’t get buried with violations about math with literal integers.
A good way to clear away the ambiguity is to assign the result of an arithmetic operation to a variable, and then use it where it’s needed. For example:
index = aa[1:0] + bb[1:0];
$display(“That value is %x”, mem[index]);
The add operation is whatever bit length index is declared with, so there’s no ambiguity about the size of the add operation.
So use ARITH_CONTEXT to point out where the length of arithmetic operations are self determined, so that two plus two keeps giving you the answer you expect.