f

#### Behavior of Arithmetic Right Shift For Verilog 2001

```Hi all,

I'm seeing some mismatching results for a Verilog 2001 arithmetic shift
operator in NCVerilog and since I don't have a Verilog 2001 LRM handy, I
thought I'd ask to experts to see if they knew what the LRM specified in
this regards.  I originally found this when we had an RTL/gates simulation
mismatch, but have extracted the problem to the following Verilog code:

module ArithmeticShiftTest;
reg signed [31:0] in;
reg        [5:0]  shift;
reg signed [31:0] out;

//calculate arithmetic barrel shift right
always@(*) out = in >>> shift;

initial begin
//set up inputs for always block
in = 32'sh80000000;//set to highest value negative number(-2147483648)
shift = 6'd32;     //shift the entire width of the word

#1; //allow time for inputs to propagate

//check output
if(out === (32'sh80000000 >>> 6'd32)) begin
\$display("PASS: 32'sh80000000 >>> 6'd32 = 0x%h", in, shift, out);
end
else begin
\$display("FAIL: 32'sh80000000 >>> 6'd32 != 0x%h,",
(32'sh80000000 >>> 6'd32), " actual = 0x%h.", out);
end
end // initial begin
endmodule // ArithmeticShiftTest

When I simulate with ncverilog (version 5.3-s005) I get the following
message:

FAIL: 32'sh80000000 >>> 6'd32 != 0xffffffff, actual = 0x00000000.

So in other words, the output of the always block is 0x00000000 when I would
expect it to be 0xffffffff (which is what the manual testbench calculation
and the synthesis come out to).  Is this a bug in NCVerilog?  What does the
Verilog 2001 LRM specify in this regards when the arithmetic shift is
greater or equal to the width of the operand?  When one envisions how one
would implement an arithmetic shift in hardware (by left-filling with the
sign bit), I would expect the answer to be 0xffffffff.

Russell

```
 0
Russell
1/18/2005 11:37:27 PM
comp.lang.verilog 3837 articles. 2 followers.

9 Replies
547 Views

Similar Articles

[PageSpeed] 48

```Russell Fredrickson wrote:

(snip)

>     //check output
>     if(out === (32'sh80000000 >>> 6'd32)) begin
>       \$display("PASS: 32'sh80000000 >>> 6'd32 = 0x%h", in, shift, out);
>     end
>     else begin
>       \$display("FAIL: 32'sh80000000 >>> 6'd32 != 0x%h,",
>         (32'sh80000000 >>> 6'd32), " actual = 0x%h.", out);
>     end

> When I simulate with ncverilog (version 5.3-s005) I get the following
> message:

> FAIL: 32'sh80000000 >>> 6'd32 != 0xffffffff, actual = 0x00000000.

If you expect 0xffffffff why do you compare to 0x80000000?

> So in other words, the output of the always block is 0x00000000 when I would
> expect it to be 0xffffffff (which is what the manual testbench calculation
> and the synthesis come out to).  Is this a bug in NCVerilog?  What does the
> Verilog 2001 LRM specify in this regards when the arithmetic shift is
> greater or equal to the width of the operand?  When one envisions how one
> would implement an arithmetic shift in hardware (by left-filling with the
> sign bit), I would expect the answer to be 0xffffffff.

I only have verilog 95 books, so I can't say for 2001.

For many languages including C and Java, and for most hardware
including x86, a shift greater than or equal to the width of the
word does not perform as you expect.  On x86 shift amount are
modulo 32, so 0x80000000 would be expected in that case.

A barrel shifter on 32 bit words could easily only use the low
five bits of the shift amount.

-- glen

```
 0
glen
1/19/2005 12:00:57 AM
```"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message
news:csk7uf\$fj0\$1@gnus01.u.washington.edu...
> Russell Fredrickson wrote:
>
> (snip)
>
> >     //check output
> >     if(out === (32'sh80000000 >>> 6'd32)) begin
> >       \$display("PASS: 32'sh80000000 >>> 6'd32 = 0x%h", in, shift, out);
> >     end
> >     else begin
> >       \$display("FAIL: 32'sh80000000 >>> 6'd32 != 0x%h,",
> >         (32'sh80000000 >>> 6'd32), " actual = 0x%h.", out);
> >     end
>
> > When I simulate with ncverilog (version 5.3-s005) I get the following
> > message:
>
> > FAIL: 32'sh80000000 >>> 6'd32 != 0xffffffff, actual = 0x00000000.
>
> If you expect 0xffffffff why do you compare to 0x80000000?

I'm not comparing to 0x80000000 but to 0x80000000 arithmetic shifted by 32
(which is surrounded by parenthesis).  I did this to illustrate the point
that not only is the result of the calculation of the always block not what
I expect, but that the same expression calculated in different way by the
same simulator yields different results!

> For many languages including C and Java, and for most hardware
> including x86, a shift greater than or equal to the width of the
> word does not perform as you expect.  On x86 shift amount are
> modulo 32, so 0x80000000 would be expected in that case.

Good point -- this is in part why I posted this -- since I realize that the
result of shifting greater than or equal to the width may not be what you
think it is.  Note that in my case -- since I have 6 bits for the right-hand
side (RHS) operand, I won't get modulo 32 on the shift as you suggest
(though I would get modulo 32 if I only were using a 5-bit RHS operator).

Thanks,
Russell

```
 0
Russell
1/19/2005 12:47:56 AM
```Russell Fredrickson wrote:
> Hi all,
>
>     I'm seeing some mismatching results for a Verilog 2001 arithmetic shift
>
> When I simulate with ncverilog (version 5.3-s005) I get the following
> message:
>
> FAIL: 32'sh80000000 >>> 6'd32 != 0xffffffff, actual = 0x00000000.
>
> So in other words, the output of the always block is 0x00000000 when I would
> expect it to be 0xffffffff (which is what the manual testbench calculation
> and the synthesis come out to).  Is this a bug in NCVerilog?  What does the
> Verilog 2001 LRM specify in this regards when the arithmetic shift is
> greater or equal to the width of the operand?  When one envisions how one
> would implement an arithmetic shift in hardware (by left-filling with the
> sign bit), I would expect the answer to be 0xffffffff.
>
>     Russell

Russel,

I ran your code through gplcver and it passed. Could it be a ncverilog
glitch?
```
 0
Jason
1/19/2005 1:04:00 AM
```Russell Fredrickson wrote:
(snip)

> I'm not comparing to 0x80000000 but to 0x80000000 arithmetic shifted by 32
> (which is surrounded by parenthesis).  I did this to illustrate the point
> that not only is the result of the calculation of the always block not what
> I expect, but that the same expression calculated in different way by the
> same simulator yields different results!

Oops, I didn't read carefully enough.    Hmmm.

>>For many languages including C and Java, and for most hardware
>>including x86, a shift greater than or equal to the width of the
>>word does not perform as you expect.  On x86 shift amount are
>>modulo 32, so 0x80000000 would be expected in that case.

> Good point -- this is in part why I posted this -- since I realize that the
> result of shifting greater than or equal to the width may not be what you
> think it is.  Note that in my case -- since I have 6 bits for the right-hand
> side (RHS) operand, I won't get modulo 32 on the shift as you suggest
> (though I would get modulo 32 if I only were using a 5-bit RHS operator).

Well, yes, but C and x86 do it with 32 bits.  Well, x86 might
use an 8 bit register, but that is still more than 5, and that
is common to many processors.

IBM S/360, S/370, and successors use six bits (modulo 64) for
both 32 bit and 64 bit shift operations, but that is unusual.

The 8086 would actually shift up to 255, the execution time
depended on the shift amount.  That was fixed in the 80286 where
the module 32 shift was introduced.

-- glen

```
 0
glen
1/19/2005 1:10:16 AM
```Jason Zheng wrote:
> Russell Fredrickson wrote:
>
>> Hi all,
>>
>>     I'm seeing some mismatching results for a Verilog 2001 arithmetic
>> shift
>>
>> When I simulate with ncverilog (version 5.3-s005) I get the following
>> message:
>>
>> FAIL: 32'sh80000000 >>> 6'd32 != 0xffffffff, actual = 0x00000000.
>>
>> So in other words, the output of the always block is 0x00000000 when I
>> would
>> expect it to be 0xffffffff (which is what the manual testbench
>> calculation
>> and the synthesis come out to).  Is this a bug in NCVerilog?  What
>> does the
>> Verilog 2001 LRM specify in this regards when the arithmetic shift is
>> greater or equal to the width of the operand?  When one envisions how one
>> would implement an arithmetic shift in hardware (by left-filling with the
>> sign bit), I would expect the answer to be 0xffffffff.
>>
>>     Russell
>
>
>
> Russel,
>
> I ran your code through gplcver and it passed. Could it be a ncverilog
> glitch?

This is the simulator output:

GPLCVER_2.10a of 10/12/04 (Sparc-Solaris).
Copyright (c) 1991-2004 Pragmatic C Software Corp.
(GPL).
See the 'COPYING' file for details.  NO WARRANTY provided.
Today is Tue Jan 18 17:09:16 2005.
Compiling source file "shift_test.v"
Highest level modules:
ArithmeticShiftTest

PASS: 80000000 >>> 32 = 0xffffffff
0 simulation events and 0 declarative immediate assigns processed.
8 behavioral statements executed (4 procedural suspends).
Times (in sec.):  Translate 0.0, load/optimize 0.1, simulation 0.1.
End of GPLCVER_2.10a at Tue Jan 18 17:09:16 2005 (elapsed 0.0 seconds).

Compilation finished at Tue Jan 18 17:09:16

I got similar results on ncverilog (5.10), however.

- Jason
```
 0
Jason
1/19/2005 1:12:15 AM
```glen herrmannsfeldt wrote:
> Russell Fredrickson wrote:
>>> For many languages including C and Java, and for most hardware
>>> including x86, a shift greater than or equal to the width of the
>>> word does not perform as you expect.  On x86 shift amount are
>>> modulo 32, so 0x80000000 would be expected in that case.
>
>
>> Good point -- this is in part why I posted this -- since I realize
>> that the
>> result of shifting greater than or equal to the width may not be what you
>> think it is.  Note that in my case -- since I have 6 bits for the
>> right-hand
>> side (RHS) operand, I won't get modulo 32 on the shift as you suggest
>> (though I would get modulo 32 if I only were using a 5-bit RHS operator).
>
>
> Well, yes, but C and x86 do it with 32 bits.  Well, x86 might use an 8
> bit register, but that is still more than 5, and that is common to many
> processors.
>
> IBM S/360, S/370, and successors use six bits (modulo 64) for both 32
> bit and 64 bit shift operations, but that is unusual.
>
> The 8086 would actually shift up to 255, the execution time
> depended on the shift amount.  That was fixed in the 80286 where
> the module 32 shift was introduced.
>

Quoting from verilog 2001 LRM

The right shift operators, >> and >>>, shall shift their left operand to
the right by the number of bit positions given by the right operand. The
logical right shift shall fill the vacated bit positions with IEEE Std
1364-2001 Version C IEEE STANDARD VERILOG� zeroes. The arithmetic right
shift shall fill the vacated bit positions with zeroes if the result
type is unsigned. It shall fill the vacated bit positions with the value
of the most-significant (i.e., sign) bit of the left operand if the
result type is signed. If the right operand has an unknown or high
impedance value, then the result shall be unknown. The right operand is
always treated as an unsigned number and has no effect on the signedness
of the result. The result signedness is determined by the left-hand
operand and the remainder of the expression, as outlined in 4.5.1.

Clearly, machine archetecture has nothing to do with the result of the
shift.

Jason
```
 0
Jason
1/19/2005 1:25:32 AM
```Jason Zheng wrote:

(snip)

> Quoting from verilog 2001 LRM

> The right shift operators, >> and >>>, shall shift their left operand to
> the right by the number of bit positions given by the right operand. The
> logical right shift shall fill the vacated bit positions with IEEE Std
> 1364-2001 Version C IEEE STANDARD VERILOG� zeroes. The arithmetic right
> shift shall fill the vacated bit positions with zeroes if the result
> type is unsigned. It shall fill the vacated bit positions with the value
> of the most-significant (i.e., sign) bit of the left operand if the
> result type is signed. If the right operand has an unknown or high
> impedance value, then the result shall be unknown. The right operand is
> always treated as an unsigned number and has no effect on the signedness
> of the result. The result signedness is determined by the left-hand
> operand and the remainder of the expression, as outlined in 4.5.1.

That sounds reasonably convincing.

The "Verilog 2001: What's New" that I could find on the web only
gave 3 as a shift value for the example.

-- glen

```
 0
glen
1/19/2005 2:19:36 AM
```I ran you code in latest version of modelsim ie 6.0 and it ran fine,
got the message as :
PASS: 32'sh80000000 >>> 6'd32 = 0x8000000032         -1
I think it should work as you expected.

-Neo

```
 0
zingafriend
1/19/2005 9:35:00 AM
```Thanks everyone for looking at this!  I started to file a bug report with
Cadence on this and in the process I was pointed to a solution that