Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

Modelsim addition bug

It seems that Modelsim truncates additions inappropriately. It appears that it uses the left hand side of an assignment to truncate the result of an additiion, even if that is not the final value. In the code below, the addition gets truncated to the length of the left hand side of the assignment first, and then further right shifted. It should preserve a bit length of the longest term in the addition plus one bit (for the carry). The truncation should only happen at the actual assignment.

module sandbox;

reg [8:0] apple;

reg [7:0] banana;

initial beginbanana = 8'hff;

apple = (banana + 1'b1)>>1;

banana = (banana + 1'b1)>>1;

$display("%x %x", apple, banana);

end

endmodule

The output is

080 00

While I expected

080 80

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    It seems that Modelsim truncates additions inappropriately. It appears that it uses the left hand side of an assignment to truncate the result of an additiion, even if that is not the final value. In the code below, the addition gets truncated to the length of the left hand side of the assignment first, and then further right shifted. It should preserve a bit length of the longest term in the addition plus one bit (for the carry). The truncation should only happen at the actual assignment.

    module sandbox;

    reg [8:0] apple;

    reg [7:0] banana;

    initial beginbanana = 8'hff;

    apple = (banana + 1'b1)>>1;

    banana = (banana + 1'b1)>>1;

    $display("%x %x", apple, banana);

    end

    endmodule

    The output is

    080 00

    While I expected

    080 80

    --- Quote End ---

    Though I sympathesise with ModelSim adding apples to bananas but the banana basket is only 8 bits so adding '1' causes overflow of basket and results in zeros which are then shifted to give zeros
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Though I sympathesise with ModelSim adding apples to bananas but the banana basket is only 8 bits so adding '1' causes overflow of basket and results in zeros which are then shifted to give zeros

    --- Quote End ---

    But there is no overflow in the line apple = (banana + 1'b1)>>1;

    The right hand side is exactly the same.

    The weird thing is that the expression "banana + 1'b1" yields different results based on the size of the left hand side.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    But there is no overflow in the line apple = (banana + 1'b1)>>1;

    The right hand side is exactly the same.

    The weird thing is that the expression "banana + 1'b1" yields different results based on the size of the left hand side.

    --- Quote End ---

    But the apple basket is 9 bits and so it does not overflow. The expression banana + 1 is evaluated correctly without overflow but then inserted into the basket and so result differs depending on basket size.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This is a tool issue. I assume the shift occurs after result of addition is put into basket rather than add shift then insert. I am just explaining my assumption about your observation.

    Or put this way: modelsim does not do any bit extension and just uses your register sizes.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    So, you are saying that if the left hand side is 8 bits, then the default size for all calculations on the right hand side will also become eight bits, even for intermediate results and even if that leads to data loss. That's a pretty poor way to do calculations.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't expect the tools to do all the work for me. So I have to observe its beheviour.

    In our mind we can add, shift...etc freely without space limitations.

    The tool in your case is told the container banana is 8 bits then you ask the tool to add 1 so it decides to throw away that extra bit (the carry bit). They could have done it the other way to include the carry bit and throw away the lsb but this is a matter of standards.

    I know if add in vhdl 1 to 8 bit register set to FF then I get zero.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I would have expected it to keep the carry bit until it was discarded in the assignment, not to discard it right away. But a bit of experimentation shows me that you are right. But when I change the code to

    banana = (banana + 1)>>1;

    I do get the expected value of 8'h80. Presumably because 1 is 32 bits long. So the length it uses is the max of the operands and the LHS.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This is a tool issue. I assume the shift occurs after result of addition is put into basket rather than add shift then insert. I am just explaining my assumption about your observation.

    Or put this way: modelsim does not do any bit extension and just uses your register sizes. .

    --- Quote End ---

    Modelsim does what IEEE 1364 requires. Before blaming the tool, take a look at the Verilog specification which discusses an example similar to the present one.

    --- Quote Start ---

    5.4.2 Example of expression bit-length problem

    During the evaluation of an expression, interim results shall take the size of the largest operand (in case of an assignment, this also includes the left-hand side). Care has to be taken to prevent loss of a significant bit during expression evaluation. The example below describes how the bit lengths of the operands could result in the loss of a significant bit.

    Given the following declarations:

    reg [15:0] a, b, answer; // 16-bit regs

    the intent is to evaluate the expression

    answer = (a + b) >> 1; //will not work properly

    where a and b are to be added, which can result in an overflow, and then shifted right by 1 bit to preserve the carry bit in the 16-bit answer.

    A problem arises, however, because all operands in the expression are of a 16-bit width. Therefore, the expression (a + b) produces an interim result that is only 16 bits wide, thus losing the carry bit before the evaluation performs the 1-bit right shift operation.

    --- Quote End ---