system-verilog

Ternary operator or always_comb with if in SystemVerilog


Suppose I have a module that takes in two numbers and a signal telling either it is signed multiplication or unsigned. Module has to multiply.

module signed_or_unsigned_mul
# (
  parameter n = 8
)
(
  input  [    n - 1:0] a, b,
  input                signed_mul,
  output [2 * n - 1:0] res
);

I tried to implemet it with ternary operator but it outputs incorrect result, e.g. -8 * -7 = 72

assign res = signed_mul ? ($signed(a) * $signed(b)) : (a * b) ;

And the code below with always_comb and if produces correct results:

  logic [2 * n - 1:0]  res_stub;
  assign res = res_stub;
  always_comb
    if (signed_mul)
      res_stub = $signed(a) * $signed(b);
    else 
      res_stub = a * b;

I dont see what's the difference between these two implementations and why they produces different outputs. Can you point it out for me please? Does additional logic variable affects this way?


Solution

  • This is because the true and false branches of the ternary operator are part of a single expression. They get evaluated in a single context. It’s the same as if you were adding the true and false expressions together. They get sized to the largest expression and if any part is unsigned, the entire expression is unsigned.

    When using the if statement you are creating two separate expressions with separate contexts.