unsigned and signed data in Verilog?

S

Shenli

Guest
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
 
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
 
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.
 

Welcome to EDABoard.com

Sponsor

Back
Top