icarus verilog signed support

T

Terry Brown

Guest
I have a design that uses signed arithmetic. Icarus will compile and
simulate, but fails miserably when the results are compared to Modelsim,
for instance. I suspect the failure is due to lack of support for signed
wires and regs in Icarus. Can anyone quickly verify the lack of signed
support in Icarus .8.1?

Thanks,

Terry Brown
 
Terry Brown wrote:
I have a design that uses signed arithmetic. Icarus will compile and
simulate, but fails miserably when the results are compared to Modelsim,
for instance. I suspect the failure is due to lack of support for signed
wires and regs in Icarus. Can anyone quickly verify the lack of signed
support in Icarus .8.1?

Thanks,

Terry Brown

Can you post your testbench code?
 
Thanks for the reply.

My code is both proprietary and way too complex to publish here.

Calculations in the code are only signed or unsigned, there is no mixture.
I have been told by Modelsim tech support (because I ran in this issue)
that Modelsim will promote a result to unsigned if there are any unsigned
terms in the calculation.

For example, if x and y are signed regs:

assign x = y * 32'h00000200;

will result in x being an unsigned number, but

assign x = y * 32'sh00000200;

results in the calculation of x as signed.

As far as correctness goes, the verilog is based on algorithms written in
C and the modelsim implementation, combined with Synplify and Xilinx ISE
6.2, creates a Xilinx FPGA that works--i.e. the hardware results match the
simulation results match the C results. Since Icarus fails on the same
code, I suspect the signed implementation in Icarus.

I will try to generate a simple example case that I can post here for
others to look at.

On Fri, 15 Apr 2005 11:49:33 -0700, sharp wrote:

The specification of signed arithmetic in the LRM is not entirely
clear, particularly for expressions that contain a mixture of signed
and unsigned operands. The correct behavior has been discussed in
committee, and some clarification is going into the next revision.
However, Mentor has not participated in that discussion. It is
possible that this is responsible for the differences in results (and
both simulators may be incorrect). If you could provide some simple
examples where they give different results, I could comment on the
correct behavior for those examples.
 
On Sat, 16 Apr 2005 17:46:37 GMT, Terry Brown <tthkbw@yahoo.com>
wrote:

Thanks for the reply.

My code is both proprietary and way too complex to publish here.

Calculations in the code are only signed or unsigned, there is no mixture.
From your example below this doesn't seem to be an accurate statement
(if it comes from your code that is.)

I have been told by Modelsim tech support (because I ran in this issue)
that Modelsim will promote a result to unsigned if there are any unsigned
terms in the calculation.

For example, if x and y are signed regs:

assign x = y * 32'h00000200;

will result in x being an unsigned number, but

assign x = y * 32'sh00000200;

results in the calculation of x as signed.
Here is what 1364.2001 says about this:

"Expression type depends only on the operands. It does not depend on
the LHS (if any).
— Decimal numbers are signed.
— Based_numbers are unsigned, except where the s notation is used in
the base specifier (as in "4'sd12")."

So the calculation of the RHS of your first expression as unsigned
seem to be justified at least as far as the standard is concerned.

I think an example of an actual mismatch would be really helpful here.
 
Wow, thanks for the info.

I tried your example, and in fact, Icarus .8.1 fails this test while cver
2.10c and Modelsim 6.0c both pass the test.

so that answers my original question and I learned a lot along the way.

Thanks,

(I removed some of your post)
On Sat, 16 Apr 2005 13:48:12 -0700, sharp wrote:


Try this example:

module top;
reg signed [3:0] factor;
reg signed [7:0] result;

initial begin
factor = -1;
result = factor * 4'shf;
$display("%b", result);
result = factor * 4'hf;
$display("%b", result);
end
endmodule

Your output should be

00000001
11100001

In the first case, you are effectively multiplying (-1)*(-1)=1
In the second case, you are effectively multiplying 15*15=225

Note that in both cases, if the output had been truncated to the same
width as the input the result would have been the same.

This testcase will show whether your simulators have implemented basic
signed arithmetic. More complex examples would be required to detect
less obvious errors in the implementation.
 
The specification of signed arithmetic in the LRM is not entirely
clear, particularly for expressions that contain a mixture of signed
and unsigned operands. The correct behavior has been discussed in
committee, and some clarification is going into the next revision.
However, Mentor has not participated in that discussion. It is
possible that this is responsible for the differences in results (and
both simulators may be incorrect). If you could provide some simple
examples where they give different results, I could comment on the
correct behavior for those examples.
 
Yes, the rules say that the result will be unsigned if there are any
unsigned operands. But it is the next step that causes confusion: If
the result is unsigned, then all operands are treated as unsigned. It
is not the signedness of the result that is the issue (after all, it
doesn't really affect the result bits if you regard them as a signed or
unsigned number), it is the intermediate operations that are performed
that affect the results. In particular, it is the extension of
operands to the full width of the result that has the biggest effect.
Most of the differences are created based on whether that extension is
zero-extension or sign-extension.

I wouldn't rely on comparison with C here. Verilog requires all
operands to be width-extended before any calculations are performed.
It does conversions as early as possible to avoid any overflow. C
waits and converts intermediate results just before they are combined
with another value that requires it. C does conversions as late as
possible. These rules can produce quite different results for mixed
signed/unsigned expressions.

In the examples you give:

For example, if x and y are signed regs:

assign x = y * 32'h00000200;

will result in x being an unsigned number, but

assign x = y * 32'sh00000200;

results in the calculation of x as signed.
What matters is not whether x is signed or unsigned (in fact x is
signed, since you declared it signed). Nor is it whether the value
assigned to x is regarded as signed or unsigned before it is assigned
to x, since that has no effect on what bits get assigned to x. What
matters is the operations performed to produce that value.

There is only a difference if x is wider than the inputs to the
multiplication (a widening multiply). For example, if y is 32 bits
wide and x is 64 bits wide to avoid losing any overflow from the
multiply. In that case, there is a difference between the signed and
unsigned versions of this operation.

Conceptually, this is the difference between a signed and unsigned
multiply. However, in Verilog there aren't actually two different
kinds of multiplies. Instead, both operands will be extended to the
size of the result before being multiplied (here I am talking about the
formal definition of the evaluation in Verilog; a synthesis tool will
presumably produce a signed or unsigned multiplier that gives
equivalent results). It is the extension operation that determines
whether you get the effect of a signed or unsigned multiplication. If
the operands are zero-extended, you will effectively get an unsigned
multiply; if they are sign-extended you will effectively get a signed
multiply.

Try this example:

module top;
reg signed [3:0] factor;
reg signed [7:0] result;

initial begin
factor = -1;
result = factor * 4'shf;
$display("%b", result);
result = factor * 4'hf;
$display("%b", result);
end
endmodule

Your output should be

00000001
11100001

In the first case, you are effectively multiplying (-1)*(-1)=1
In the second case, you are effectively multiplying 15*15=225

Note that in both cases, if the output had been truncated to the same
width as the input the result would have been the same.

This testcase will show whether your simulators have implemented basic
signed arithmetic. More complex examples would be required to detect
less obvious errors in the implementation.
 

Welcome to EDABoard.com

Sponsor

Back
Top