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.)