From: Clifford E. Cummings (cliffc@europa.com)
Date: Thu Jun 05 1997 - 09:55:05 PDT
Subject: BTF - B19- Cadence signed arithmetic proposal
Behavioral Task Force - Enhancement Request
Assigned Enhancement Request Number: B19
Enhancement Name (Description): Cadence signed arithmetic proposal
Date Submitted: 970409
Requestor: tfitz@cadence.com (Tom Fitzpatrick)
Status: RO
Is enhancement intended to be synthesizable?: Yes
Subject: Proposal for Signed Wires and Regs in Verilog
Signed Arithmetic in Verilog
A Proposal to the IEEE 1364 Committee
Tom Fitzpatrick
Cadence Design Systems
1.0 Problem Statement:
The Verilog-HDL does not currently support signed arithmetic for
arbitrarily sized regs and wires. This functionality would be extremely
useful for hardware designers to be able to model complex mathematical
operations, and we at Cadence feel that the IEEE 1364 Committee should
consider adding this functionality to the language.
One of the primary requirements for the committee, in extending the Verilog
language, is to preserve the current functionality of the language, which
for the most part is defined by the behavior of the Verilog-XL
simulator. To this end, we have done an extensive investigation to
understand how Verilog-XL treats the only existing signed construct in the
language: the integer. The rules proposed here are an extension of current
rules used by Verilog-XL to handle integer operations, as well as mixtures
of integers and regs, which should be applicable to the general case of
regs and wires.
2.0 Solution:
Add support for arbitrarily signed sized objects to Verilog-HDL and VPI.
3.0 Verilog-HDL changes:
The elements that need to support being typed as signed are:
nets
registers
memories
HDL functions
User system functions (VPI)
io decls.
Except for User system functions, the object can be typed as being signed
by using the keyword "signed" in the definition of the object. The
functionality of the VPI interface will be enhanced to deal with the new
typed objects, the PLI 1.0 interface will not.
The only influence typing a net as signed will have is when the net is used
in an expression. Then the value of the entire net will be treated as a
signed value. The individual bits (if any) of the net will still be
derived from the resolved value of all of the net's drivers.
The signed attribute will not cross hierarchy. If a user wants the signed
type to cross hierarchy they will have to add the signed keyword to the
objects declaration at the different levels of hierarchy. Any expressions
on a port will be treated as any other expression in an assignment. It
will be typed, sized, evaluated and the resulting value assigned to the
object on the other side of the port using the same rules as an assignment.
A based constant can be typed as being signed by preceding the base type
with an "s". If the base type is not preceded with an "s" the constant
will be unsigned.
Two new arithmetic operator will be added to the language:
arithmetic shift right ASR ">>>"
arithmetic shift left ASL "<<<"
Two new systems functions will be added to handle type casting on
expressions $signed() and $unsigned(). These functions will evaluate the
input expression and return a value with the same size and value of the
input expression and the type defined by the function:
$signed -- signed
$unsigned -- unsigned
examples:
wire signed [3:0] signed_wire; // range -8 <-> +7
reg signed [3:0] signed_reg; // range -8 <-> +7
reg signed [3:0] signed_mem [99:0]; // 100 words range -8 <-> +7
function signed [3:0] signed_func; // range -8 <-> +7
out = in <<< 1;
tmp = tmp >>> 1;
4'd1 // 4 bit unsigned decimal 1
-4'd1 // 4 bit unsigned decimal -1
4'sd1 // 4 bit signed decimal 1
-4'sd1 // 4 bit signed decimal -1
The signed keyword may be included in an input, output or inout
declaration; however, if there is also a secondary declaration of the wire
or register aside from that of the I/O declaration, then the sign of the
secondary declaration must match that of the I/O declaration.
For example, the following are legal:
input signed signed_input;
wire signed signed_input;
input unsigned_input;
wire unsigned_input;
input signed another_signed_input;
And the following are illegal:
input signed signed_input;
wire signed_input;
input signed_input;
wire signed signed_input;
3.1 Determining the resultant type of an expression:
The value of signed quantities will be represented with two's complement
notation. The following are the rules for determining the resulting type
of an expression:
1. Expression type depends only on the operands. It does not depend on the
LHS (if any).
2. Decimal numbers are signed.
3. Based_numbers are unsigned.
4. Parameters are signed if and only if the RHS expression assigned to the
parameter is signed
5. Bit_sel results are unsigned, regardless of the operands.
6. Part_sel results are unsigned, regardless of the operands.
7. Concatenate results are unsigned, regardless of the operands.
8. Comparison results (1, 0) are unsigned, regardless of the operands.
9. Reals converted to integers by type coercion are signed
10. The sign and size of any self-determined operand is determined by the
operand itself and independent of the remainder of the expression.
11. For non-self-determined operands the following rules apply:
if any operand is real, the result is real.
elseif any operand is unsigned, the result is unsigned, regardless
of the operator
elseif all operands are signed, the result will be signed,
regardless of operator, except as noted.
3.2 Steps for evaluating an expression:
1. Determine the expression size based upon the standard rules of expression
size determination.
2. Determine the sign of the expression using the rules outlined in
Section 3.1
3. Coerce the type of each operand of the expression (excepting those which
are self-determined) to the type of the expression.
4. Extend the size of each operand (excepting those which are self-determined)\
to the size of the expression. Perform sign extension if and only if the
operand type (after type coercion) is signed.
3.3 Steps for evaluating an assignment
1. Determine the size of the RHS by the standard assignment size determination
rules (the greater of the sizes of the LHS and RHS).
2. If needed, extend the size of the RHS, performing sign extension if and
only if the type of the RHS is signed.
3.4 Arithmetic shift operators:
The ASR preserves the sign bit if the operand is signed, while the ASL does
not, ASL is identical to a logical left shift. These operators are legal
wherever the logical shift operators are and have the same precedence as
the logical shift operators.
3.5 Dealing with "X" or "Z":
If a signed operand is to be resized to a larger signed width and the value
of the sign bit is "X", the resulting value will be bit filled with
"X"s. If the sign bit of the value is "Z", then the resulting value will be
bit filled with "Z"'s. If any bit of a signed value is "X" or "Z" then any
non logical operation involving the value will result in the entire
resultant value being an "X" and the type consistent with the expressions
type.
4.0 VPI
To register a function as being signed the user will set the sysfunctype
field of the t_vpi_systf_data structure to the value of
vpiSysFuncSignedSized.
Calling vpi_get() with the property vpiSigned will return TRUE on the
following objects if they have the signed attribute:
vpiIODecl, any object in the expression class.
Two new expression properties need to be added to the VPI include file for
the two new operators:
ASL vpiArithLShiftOp
ASR vpiArithRShiftOp
Date: Wed, 09 Apr 1997 15:04:04 -0400
From: Elliot Mednick <elliot@wellspring.com>
I have some fundamental objections to this proposal. This is similar to one
that was brought up in the OVI Language Committee a few years ago. A
modified version (which met with my approval, though it was still marginal)
made it into OVI LRM 2.0 and was then cut for IEEE-1364, which was just as well.
I will argue my case in the correct forum. I just wanted to let The List
know that this won't go through uncontested.
Date: Wed, 9 Apr 1997 18:08:47 -0700 (PDT)
From: <mac@silicon-sorcery.com>
I as well, have some serious detailed questions about the proposal as is.
And while some of my objections may be shared with Elliot's, likely he will
disagree with me about some as well.... I guess thats why it's called a
committee!
Date: Thu, 10 Apr 1997 10:20:51 -0400
From: Elliot Mednick <elliot@wellspring.com>
I would be happy to share my objections. I sent a quick private email to
Tom outlining my arguments. Someone tell me if 1364core is the right list
to do this, or tell me which list to use, and I will comment in detail.
From: "Thomas Fitzpatrick" <tfitz@cadence.com>
Date: Wed, 7 May 1997 10:14:21 -0400
There were a few issues that came up at Monday's discussion of this proposal,
and I'd like to address some of them now.
The number of bits in a signed division operation: (example -8/-1 = 8)
If the size of the operation is not big enough to hold the full value
of the result, then the result is truncated to the length of the operation. The
errant behavior of the prototype I mentioned is a bug and has been pcr'd.
What to do with "-4'd1": Mac mentioned that Verilog-XL has always treated
this as if the unary "-" operation is applied to the constant "4'd1". That's
not quite true. According to the 1364 spec (p 30), "an integer with a base
specifier shall be interpreted as an unsigned value." Therefore, where the
proposal lists
-4'd1 // 4 bit unsigned decimal -1
if this were assigned to an integer, or a signed reg of more than 4 bits, the
value should be zero-extended. Because based numbers are interpreted as
unsigned, we proposed the
-4'sd1 // 4 bit signed decimal -1
notation to be able to specify a signed, based number.
All of the other issues were simply places where the spec was not as
rigourous as it should be, but the intended behavior is as we all expected. I
will be updating the proposal shortly.
From: <mac@silicon-sorcery.com>
Date: Wed, 7 May 1997 10:10:42 -0700 (PDT)
> There were a few issues that came up at Monday's discussion of this
> proposal, and I'd like to address some of them now.
> ...
> What to do with "-4'd1": Mac mentioned that Verilog-XL has always treated
> this as if the unary "-" operation is applied to the constant "4'd1". That's
> not quite true. According to the 1364 spec (p 30), "an integer with a base
> specifier shall be interpreted as an unsigned value." Therefore, where the
> proposal lists
> -4'd1 // 4 bit unsigned decimal -1
>
> if this were assigned to an integer, or a signed reg of more than 4
> bits, the value should be zero-extended. Because based numbers are
> interpreted as unsigned, we proposed the -4'sd1 // 4 bit signed
> decimal -1 notation to be able to specify a signed, based number.
>
In 1364 Verilog, The 4'd1 is treated as an unsigned value.
The EXPRESSION -4'd1 applies the operator UNARY_MINUS to the
unsigned value 4'b0001.
The expression bit length rules are then applied:
1) examine the rhs expression, as a tree, starting at the
root. Determine the width of the result of the expression, based on
the width of the operands to the expressions, and the operators
applied to them, consulting the operator width table. Here we have
UNARY_MINUS(4'd1);
according to the table, the unary minus operator passes along
the width of it's operand, which in this case is 4 bits.
2) determine the width of the lhs expression. Here we see a 32
bit container, and no operators.
3) increase the size of each operand and expression to the
maximum of the size of the left hand side and right hand side
expressions. (again, subject to the operator width table's exceptions)
Therefore we increase 4'd1 to 32'd1, and yes, ZERO EXTENDING, as 4'd1
is an unsigned number.
After sizing is complete, then THEN the expression is
evaluated, and hence the unary minus operator is applied, converting
32'b0000_0000_0000_0000_0000_0000_0000_0001 into
32'b1111_1111_1111_1111_1111_1111_1111_1110
My understanding (which could be wrong) of the proposal is
that the proposed change would make the '-' part of the constant 4'd1,
and hence the rhs expression is simply the constant 4'd15, which after
sizing, gets zero extened to 32'd15, and then is simply assigned to
the RegA and the IntA, each which get 15.
Run this example on XL:
module one;
integer IntA;
reg [31:0] RegA;
initial begin
IntA = -4'd1;
RegA = -4'd1;
$display("IntA %d",IntA);
$display("RegA %d",RegA);
end // initial begin
endmodule // one
I get:
Highest module (one)
IntA -1
RegA 4294967295
<p> So, my point is with the proposed change, we would be making
the behavior of existing simulators incorrect, which is a big step,
one which needs a lot of justification, none of which I have seen.
Moreover, my understanding is there is no proposal to change
the behavior of the following, which leaves us with a non useful
inconsistancy:
module one;
integer IntA;
reg [31:0] RegA;
reg [3:0] a;
initial begin
a = 4'd1;
IntA = -a;
RegA = -a;
$display("IntA %d",IntA);
$display("RegA %d",RegA);
end // initial begin
endmodule // one
The above, of course currently behaves exactly as does the
previous code:
IntA -1
RegA 4294967295
The proposed change where -4'd1 is treated as 4'hf, leaves
this expression alone, the old rules apply, and hence my understanding
is that the proposal would have the first program printing
IntA 15
RegA 4294967295
and the second printing:
IntA -1
RegA 4294967295
From: Elliot Mednick <elliot@wellspring.com>
Date: Fri, 09 May 1997 14:58:32 -0400
Here is my opinion on Signed Arithmetic for Verilog.
STATEMENT
I agree that signed arithmetic should be part of the Verilog language. I do
not agree with the proposed implementation.
SUMMARY
There are (at least) two ways to represent signed arithmetic in a
programming language: using signed operands and using signed operators. B19
takes the signed operand approach. I strongly feel that Verilog should use
signed operators to implement signed arithmetic.
ARGUMENT
Most high-level languages, like C, implement signed arithmetic by
introducing the signed data type. This overloads the operator. For
instance, there are really two integer divide operators, one for signed and
one for unsigned (and one for real, one for double, etc.). This is fine for
a "real" programming language, where the intent is to "program" or control
something. In C, data type abstraction is a Good Thing and hiding details
is good.
Verilog, by contrast, is used to "describe" something. Verilog code is
written as a description of some hardware. The fact that it is executed is
really secondary. It is executed only to test the description. The real
value in Verilog code is that it is later parsed -- by synthesis tools or by
humans who use Verilog code as an "executable specifications". Thus, we
need to see as much as possible what is going on in the code and not hide
anything. (The exception to this is for architectural-level code which
indeed to for execution, so, in this case only, abstract data types are Good.)
So, in Verilog, the data types correlate to some aspect of hardware. Under
the right circumstances, the data type "reg" describes, indeed, a hardware
register. Hardware registers are containers, descriptions. When we
describe a register, we don't care what's in them. Thus, there is no
concept of "signed" and "unsigned". When you draw a schematic of a
register, you don't lay a "signed D flop".
What you *do* draw are signed operators. There is a difference between a
signed divide unit and an unsigned divide unit.
Lets take a general case. Say you are designing an ALU (Arithmetic Logic
Unit). The ALU contains a number of arithmetic functions like addition,
subtraction, divide, multiple -- all signed and unsigned. The ALU is fed by
a register file. If you are writing the Verilog code to describe this, do
you make the register file signed? Or unsigned? My answer in neither; you
make the operators signed and unsigned.
By adding signed registers to the language, the whole language suddenly gets
more complex. You need rules for data promotion and conversion, and all the
overloading rules. Mapping signed registers to hardware is a problem and
synthesis is a problem.
In contrast, by adding signed *operators* to the language, implementation is
simple -- almost, but not quite trivial -- and the usage is also
straightforward.
There is precedence for this method. An early hardware description language
called ISP (Instruction Set Processor) was described in Siewiorek, Bell, and
Newell's book _COMPUTER STRUCTURES; PRINCIPLES AND EXAMPLES_. (I'm in the
process of moving, so the book is temporarily packed away. I'll try to get
it out in the next couple of weeks.) In it, they used a concept of operator
modifiers. Signed/unsigned is one of the modifiers.
So, I informally propose (that is, I propose the concept but I am not
proposing the actually wording) that we reject B19 and add the following
operators to the Verilog language:
igned multiply
signed divide
signed relational operators
signed right shift (sign extend)
(Are there others?)
If two unequal-length registers are being combined using a signed operator,
then the smallest is extended, using the general rules of expression
lengths, except using sign extension. Negative numbers are defined as the
high bit of the operand being set and the rest of the bits are twos compliment.
As for syntax, I am open, but propose either of these two:
igned multiply :* `*
signed divide :/ `/
signed relational operators :> :< :>= :<= `> `< `>= `<=
signed right shift :>> `>>
I slightly prefer the back tick because it makes it look like a compiler
modifier. I can understand arguments against it, since back ticks are now
used as macros and compiler directives, but I think that the modification to
the lexical analyzer of a Verilog tool would be trivial.
I would optionally add the `signed and `unsigned compiler directives to
delimit regions which modify all operators past the directive. Thus:
`signed
snafu = foo / bar; // this is a signed divide.
This greatly reduces the problem of signed arithemtic, makes it easy to
implement, easy to use, easy to read, easy to write and easy to synthesize.
I think it also makes PLI implementation easier because it only requires a
few -- optional -- utility functions. No data types are added or changed.
From: <mac@silicon-sorcery.com>
Date: Fri, 9 May 1997 13:42:49 -0700 (PDT)
1) Note: one needs a signed modulus operator as well.
2) Verilog already has typed data: the unsigned type, the real type,
and the integer type. Would you have us remove these existing
types? Replacing integer with just a reg [31:0] and then using the
signed operators when needed, works fine, but:
Replacing real with reg [63:0], and using new real operators
requires for + - * / % < <= >= > ==, and = as well. (it also would
potentially allow appling real operations on objects of size other
than REAL*8, albeit if this was interesting, we could just and a
range to the real type
3) Another large use for Verilog (other than the two you pointed out
of specifing hardware, and of prototyping hardware) is writing
testbenchs for hardware; and I submit, this is the spot where
signed and real types are of the most use.
4) using ` prefix for signed operators is perhaps the easiest in terms
of jamming this feature into the language; it by no means is
obvious or elegant. The ` tells me these operators are DIFFERENT;
but doesn't tell me why or in what way. To a new user it will be
confusing. With the added requirement that we need new operators
for real, one needs to get even more creative. `s< and `r< perhaps?
So while it is definately an intriguing proposal, I am afraid that
since it is a rather radical change to the language, one which is
incompatible with existing integer and real types, that I am leaning
against this proposal.
However, let the discussion continue!
From: Vivek Sagdeo <vivek@professionals.com>
Date: Fri, 9 May 1997 16:59:42 -0700 (PDT)
i. The signed operators are implicitly defined in the signed operand
approach. In any programming language, operator overloading whereby we use the
same symbols to represent operations on operands of different types is
a well-established practice. "C" uses same "+" operator for signed, unsigned
int types as well as floating point types. Thus, need of new operaor symbols
should be obviated. We use the same operators *. /, >, <, << << and others
defined for unsigned arithemtic in Verilog as of now.
>>E Mednick writes :
>>As for syntax, I am open, but propose either of these two:
>>signed multiply :* `*
>>signed divide :/ `/
>>signed relational operators :> :< :>= :<= `> `< `>= `<=
>>signed right shift :>> `>>
2. In my proposal, I suggested that one only needs 'signed' declarations.
The implicit assumption here is to use the signed arithemtic as we commonly
know. In Verilog 1364, signed arithmetic exists with integers and constants.
What is lacking is ability to save signed values in registers of varying
widths.The main goal of this extension should be to address this feature and
this
is achieved by the 'signed' declarations. Everything else basically follows
existing syntax and semantics. As I proposed earlier, the whole extension
can be summarized in the following 3 lines.
1. Signed regs are declared using 'reg signed <size> <identifier>;'
syntax.
2. All signed quantities behave like integers and are extended
following the same rules of 1364. Thus, to obtain results of
operations on 2 signed operands, replace those with equivalent
signed constants and then perform the operation as in 1364.
3. All expressions containing signed and unsigned quantities are treated
as unsigned expressions.
With this extension, we extend the language consistently and addressing
the precise need in signed arithmetic without opening a whole new
can of worms ....
//********************************************************************//
// Cliff Cummings E-mail: cliffc@europa.com //
// Sunburst Design Phone: 503-579-6362 / FAX: 503-579-7631 //
// 15870 SW Breccia Dr., Beaverton, OR 97007 //
// //
// Verilog & Synthesis Training / On-Site Training //
// Verilog, VHDL, Synopsys, LMG, FPGA, Consulting and Contracting //
//********************************************************************//
This archive was generated by hypermail 2.1.4
: Mon Jul 08 2002 - 12:54:40 PDT
and
sponsored by Boyd Technology, Inc.