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. Thanks in advance, Russell

0 |

1/18/2005 11:37:27 PM

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 |

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 |

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. > > Thanks in advance, > Russell Russel, I ran your code through gplcver and it passed. Could it be a ncverilog glitch?

0 |

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 |

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. >> >> Thanks in advance, >> 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. All Rights reserved. Licensed under the GNU General Public License (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 |

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 Copyright � 2001 IEEE. All rights reserved. 49 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 |

1/19/2005 1:25:32 AM

Jason Zheng wrote: (snip) > Quoting from verilog 2001 LRM > Copyright � 2001 IEEE. All rights reserved. 49 > 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 |

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 |

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 mentioned that they knew about this issue and it is fixed in a later service release of the NCVerilog than I am using. Thanks again! Russell

0 |

1/19/2005 7:33:30 PM