Sign extension during comparative operation

Hi,

I tried to write a comparison of 2 signed vectors with code like this:
if (vec4bit < -3’sd4)

vec4bit is signed [3:0] with a value of 1. I expected the result of this comparison to be false. But my simulator returns true. I used a display statement to test out what is going on:

$display(“%d”, 4’sd1 < -3’sd4);
1

The explanation I’ve gotten is this:

Verilog 2005 LRM section 5.1.7 Relational operators captures below:

When both operands are signed, the expression shall be interpreted as a comparison between signed values. If the operands are of unequal bit lengths, the smaller operand shall be sign-extended to the size of the larger operand.

And here were the steps they took:
4’sd1 < -3’sd4
4’sd1 < 4’(-3’sd4)
4’sd1 < -(4’(3’sd4))
4’sh1 < -(4’(3’sb100))
4’sh1 < -(4’sb1100)). // sign extension
4’sh1 < 4’sb0100 // 2’s complement

But I believe that step 3 is wrong. In step 3, the negation is moved outside until after the extension is done. I can’t find anywhere in the standard where it explicitly states that it should be done this way. In addition, if you compare this way:
$display(“%d”, 4’sd1 < $signed(-3’sd4));
0

The result is correct. Does it make sense that a needless cast should change the result?

Can someone please shed some light on this. I’ve tried this in VCS and Incisive, as well as the other simulators available on edaplayground. I don’t have ModelSim. All the simulators I’ve tested on produce the same unexpected result.

I realize that this behavior ONLY affects the max negative number. All other numbers work out the same both ways.

Thanks,
Nachum

In reply to nachumk:

You should be using the 1800-2012 LRM, and this is explained in _11.8.2 Steps for evaluating an expression
_

Your expression is syntactically equivalent to

4’sb0001 < -( 3’sb100 )

And the rules state that you need to propagate the size relational expression back down to the
context-determined operands of the expression BEFORE APPLYING ANY OPERATORS

4’sb0001 < -( 4’(3’sb100) ) // sign extend operands first.
4’sb0001 < -( 4’sb1100) )

4’sb0001 < 4’sb0100) // then apply negation
1’b1 // result

What the cast does is prevent the propagation of the context so that -3’sd4 is evaluated in a self determined context.

I would go back an re-think why you need to be comparing two different sized, signed operands.

In reply to dave_59:

Hi Dave,

I feel more comfortable if you agree with this behavior as I believe you are on the committee… But I don’t really get why SV would want this behavior. Seems like evaluating -3’sd4 first and then sign extending would make a lot more sense. I will need a lot more time to comprehend those expression evaluation paragraphs.

In response to your critique, I can easily change my code. But I like to understand the behavior of the tools and languages. I don’t throw away opportunities to learn something, and this was one such opportunity.

Thanks for the explanation,
Nachum