# unsigned and signed data in Verilog? - verilog

This is a discussion on unsigned and signed data in Verilog? - verilog ; Hi all, I am reading &quot;Coding Guidelines for Datapath Synthesis&quot; from Synopsys. And confused with the example below, why split unsigned and signed + and *? //=====Unintended behavior====== input signed [3:0] a; input signed [7:0] b; output [11:0] z; // ...

1. ## unsigned and signed data in Verilog?

Hi all,

I am reading "Coding Guidelines for Datapath Synthesis" from Synopsys.
And confused with the example below, why split unsigned and signed +
and *?

//=====Unintended behavior======
input signed [3:0] a;
input signed [7:0] b;
output [11:0] z;

// product width is 8 bits (not 12!)
assign z = \$unsigned(a * b);
// -> 4x8=8 bit multiply
//============================

//======Intended behavior======
input signed [3:0] a;
input signed [7:0] b;
output [11:0] z;
wire signed [11:0] z_sgn;

// product width is 12 bits
assign z_sgn = a * b;
assign z = \$unsigned(z_sgn);
// -> 4x8=12 bit multiply
//============================

Best regards,
Davy

2. ## Re: unsigned and signed data in Verilog?

Davy,

My guess is the "\$unsigned" system task breaks the context deterined
expression so the multiplcation can't "see" the width of the result
from the LHS. Therefore, the bit length of the multiply is the maximum
bit width of the multiplicands, in this case 8.

One thing I don't understand is why you can't just do

assign z = a*b;

According to the LRM, the signed-ness of the expression is supposed to
ignore the type of the LHS.

David Walker

On Jan 25, 11:08 pm, "Shenli" <zhushe...@gmail.com> wrote:
> Hi all,
>
> I am reading "Coding Guidelines for Datapath Synthesis" from Synopsys.
> And confused with the example below, why split unsigned and signed +
> and *?
>
> //=====Unintended behavior======
> input signed [3:0] a;
> input signed [7:0] b;
> output [11:0] z;
>
> // product width is 8 bits (not 12!)
> assign z = \$unsigned(a * b);
> // -> 4x8=8 bit multiply
> //============================
>
> //======Intended behavior======
> input signed [3:0] a;
> input signed [7:0] b;
> output [11:0] z;
> wire signed [11:0] z_sgn;
>
> // product width is 12 bits
> assign z_sgn = a * b;
> assign z = \$unsigned(z_sgn);
> // -> 4x8=12 bit multiply
> //============================
>
> Best regards,
> Davy

3. ## Re: unsigned and signed data in Verilog?

dbwalker0min@gmail.com wrote:
> My guess is the "\$unsigned" system task breaks the context deterined
> expression so the multiplcation can't "see" the width of the result
> from the LHS. Therefore, the bit length of the multiply is the maximum
> bit width of the multiplicands, in this case 8.

Yes. System function arguments are self-determined.

> One thing I don't understand is why you can't just do
>
> assign z = a*b;
>
> According to the LRM, the signed-ness of the expression is supposed to
> ignore the type of the LHS.

Agreed. David's simple approach should work fine.

Perhaps the tool has a bug in this area. Or perhaps the
person writing this example didn't know this particular
rule. Or perhaps they were so unclear on the rules that
they felt they needed to stick in explicit conversions in
this case. Or maybe they felt that it was easier for the
user to understand using explicit rather than implicit
conversion to unsigned.

Use of the \$signed and \$unsigned system functions
can cause confusion. In most cases their effect in
shielding their argument is more powerful than the
conversion that they provide. Using \$signed on one
operand of an expression when there are still other
operands that are unsigned will not make anything
signed. The result will immediately be converted back
to unsigned, as with any signed operand in an
unsigned expression. Unless it makes all of the
operands signed, so that the expression is signed,
\$signed will have the same effect that \$unsigned
would have.