Assignment rules for different width & sign

Hi Moderators,

I am new to SV and am currently trying to understand sign extension / zero padding in an assignment

bit [7:0] A,B;
bit signed [7:0] A_S;

bit [30:0] b;  
bit signed [30:0] s_b;

initial begin:i1
  A_S = -4'sd4;  // -4'sd4 is 'b1100
  $display("A_S is 'b%b i.e 'd%0d",A_S,A_S);
    A = -4'sd4;
  $display("A is 'b%b i.e 'd%0d",A,A);
end

Both assignments perform sign extension while I was expecting it only for 1st assignment to A_S ( as lhs is signed type )

[Q1] Does sign extension take place independent of sign type of lhs ?

[Q2] When MSb of rhs is 1, what decides whether sign extension or zero padding is performed ?

initial begin:i2
  B = $signed(4'b1100) + $signed(4'b1111);
  $display("B is 'b%b i.e 'd%0d",B,B);
end

Similar to i1 I observe that ini2 both operands in rhs are sign-extended to 8-bits before addition operation ( although lhs is unsigned type )

[Q3] What gets determined first ? Is it the sign type or bit length ?

initial begin:i3
 // Both LHS & RHS are 31-bits wide so No Sign Extension / Zero padding here
    s_b = 31'h7FFF_FFFF; 
      b = 31'h7FFF_FFFF;
    $display("32'(s_b) is 'b%b i.e 'd%0d",32'(s_b),32'(s_b)); 
    $display("32'(b)   is 'b%b i.e 'd%0d",32'(b),32'(b));
end

[Q4] Although both b and s_b have MSb as 1,

why does sign extension occur for 32’(s_b) while zero padding is done for 32’(b) ?

[Q5] As per LRM what is an expression type ? Is it only sign and bit-width ?

Thanks & Regards,

Aakash B

The assignment behavior is determined by both the width and the signedness of the right-hand-side expression.

  • If the RHS is wider than the destination, the most significant bits are truncated.

  • If the RHS is narrower, it is extended to match the destination width:

    • Zero-extension if the RHS expression is unsigned.

    • Sign-extension if the RHS expression is signed.

For example:

logic [3:0]  a;
logic [7:0]  b;
logic signed [3:0] s;

a = b;   // a = b[3:0] (upper bits discarded)

b = a;   // b = {4'b0000, a} (zero-extended)

b = s;   // sign-extended because s is signed

One thing that often surprises people is that the signedness of the expression matters, not just the declared type of the destination. If the intent is to make the conversion explicit and avoid tool warnings or ambiguity, using an explicit cast (for example, $signed(), $unsigned(), or a size cast) is generally the best practice.

Thanks.

Any thoughts / comments on Q5 ?

The term expression type in the SystemVerilog LRM means more than just the declared data type of a variable. It refers to the type that results after the language applies all of the expression evaluation rules.

For most integral expressions, the expression type includes:

  • Bit width (size)

  • Signedness (signed or unsigned)

These two properties determine how operands are extended, how arithmetic is performed, and how the final result is assigned.

However, the expression type is not always limited to width and signedness. An expression also has a base data type (for example, int, logic, bit, byte, integer, enum, etc.), and some operators preserve or derive that type according to the rules in IEEE 1800. For example, a comparison expression always produces a 1-bit logical result regardless of the operand widths, while a concatenation creates an unsigned packed vector whose width is the sum of its operands.

So, if you’re asking specifically about integral assignment and arithmetic rules, width and signedness are the key attributes of the expression type. But in the broader LRM sense, an expression’s type also includes its underlying data type, depending on the kind of expression being evaluated.

Thanks .

Would it be possible to share an example where the data type 2-state / 4-state has an impact ?

In the example above only the width and sign of the expression was of importance

Your questions are quite broad, making it difficult to learn SystemVerilog by asking one question at a time on a forum. As a hardware description language, SystemVerilog has very detailed rules about how types interact in an expression because we’re trying to describe hardware as succinctly as possible. In most software, languages, and expressions, code is optimized for the hardware platform it executes on, such as an Intel processor. I suggest you search for some tutorials on the SystemVerilog type system.