Casting between signed and unsigned values and variables

In this example:

module tb1;
  bit signed [3:0] a;
  bit unsigned [4:0] b;
  logic unsigned [15:0] u = -4'd12;
  initial begin
    a = -4'sd12;
    b = 5'd13;
    $display( -4'sd12 + 5'd13,, $typename( -4'sd12 + 5'd13), $bits( -4'sd12 + 5'd13));
    $display( a + b,, $typename( a + b), $bits( -a + b));
  end
endmodule

The result is: 1 bit[4:0] 5 for the first display and 17 bit[4:0] 5 for the second one.
Does anyone know why -4’sd12+5’d13 = 1 but a+b = 17 ?
I tried Questa, Vcs, Aldec, and Xcelium and all gave the same result. but i think both should be 17.

I couldn’t find any explanation for this weird behavior

Remember that operands are extended before operators are applied. When you write a+b the negation of -4’sd12 is on 4 bits, and has the value 4. But in the expression -4’sd12+5’d13, you are actually negating -5’sd12, which is 20. 20+13 is 33 (6’h21) and gets truncated to 5 bits and you are left with the value 5’d1.

You are asking for trouble, mixing signed and unsigned values of different widths in the same arithmetic expression.

Hi @dave_59,
Thank you for your reply!
I think my problem was that I thought when we say extending first then this means 5'(-4'sd12) which is value of 4 but this wrong and I learned from you now that it means literally -5'sd12 which is 5'b10100.
and the operand a in the expression a+b is already stored in the memory with 4'b0100 so when we extend it to 5 bits it will be 5'b00100 so the result would be 17.