8.演算子

オペランドになりえる種類 備考
定数 (realも含む) 3'b001、24, 16'hzzzz REALで出来る演算子は限られる。
Net wire [3:0] a;  a
Variables : reg,integer,time,real,and realtime reg [3:0] b;  b
Net ビットセレクト a[1]
Variable ビットセレクト: reg,integer,and time b[3]
Net パートセレクト a[2:1]
パートセレクト: reg,integer,and time b[3:1] 
アレーの要素 reg [7:0] c[0:3];  c[3]
ファンクションで上記のタイプを返すもの

オペレーター

{} {{}} 連接 Real
+-*/** 算術演算、**は、Verilog2001 Power演算
% モジュロ演算
> >= < <= 比較演算
! 論理否定
&& 論理積
|| 論理和
== Logical equality
!== Logical inequality
=== Case equality
!== Case inequality
~ Bit-wise NOT
& Bit-wise AND
| Bit-wise OR
Bit-wise EXOR
^~or ~^ Bit-wise equivalence
& Reduction AND
~& Reduction nand
| Reduction or
~| Reduction nor
^ Reduction xor
~^ or ^~ Reduction xnor
<< Logical Shift Left
>> Logical Shift Right
<<< Arithmatic Shift Left(Verilog2001動作的には<<と同じ)
>>> Arithmatic Shift Right(Verilog2001)
?: Ternary ( C言語に同じ)
or イベントのOR


演算子の優先度

+ - ! ~ (単項) 最上位
**
*/%
+ - (2項)
<< >> <<< >>>
< <= > >=
== != === !==
& ~&
^ ^~ ~^
| ~|
&&
||
?:(conditional operator) 最下位

8.1 オペランド
8.1.1 bit select とpart select
宣言レンジを越えたときは、xが返ります。

reg [3:0] a;
reg b;
integer i;
initial begin
 i=4;
 b=a[i];//宣言レンジを越えているのでxが返る
end

パートセレクトは2種類あります。
一つ目は、

vect[msb_expr :  lsb_expr]

でmsb_expr と lsb_expr共、定数でなければなりません。
二つ目は、Verilog2001仕様で、

reg [15:0] big_vect;
reg [0:15] little_vect;

big_vect[lsb_base_expr +: width_expr]
little_vect[msb_base_expr +: width_expr]
big_vect[msb_base_expr -: width_expr]
little_vect[lsb_base_expr -: width_expr]

で、width_exprは、定数でなければなりませんが、lsb_expr、msbexprは、変数でOKです。


8.1.2 string について

 

この実行結果は、次のようになります。右詰めにされて左側は0padされます。


Hello Veritak World is stored as 00000048656c6c6f205665726974616b20576f726c64
Hello Veritak World!!! is stored as 48656c6c6f205665726974616b20576f726c64212121


8.2 Integer Numberについて

   integer IntA;
   IntA = -12 / 3; //−4になります。 The result is -4.
   IntA = -’d 12 / 3; // 1431655761になります。
   IntA = -’sd 12 / 3; //Verilog2001 -4になります。
   IntA = -4’sd 12 / 3; //Verilog2001 1になります。 4'sd12=.1100,符号付なので、-4 Unary演算で、-(-4)=>4 4/3=1

8.3 算術演算子

a+b
a-b
a*b
a/b
a%b

8.3.1 モジュロオペレータ

演算 結果
10 %3
11 %3 2
12 %3 0
-10 %3 -1 符号は、第一オペランドを取る
11 %-3 2 符号は、第一オペランドを取る
-4'sd12%3 1 -4'sd12は、4です。(Verilog2001)

8.3.2 算術表現の符号

タイプ Signed/Unsigned
net signed 宣言のないnetはUnsigned
reg signed 宣言のないnetはUnsigned
signed net Signed
signed reg Signed
integer Signed 
time Unsigned
real,realtime Signed,floating point


8.3.3 除算の符号(Verilog2001)

reg [15:0] regA;
reg signed  [15:0] regS;
integer intA;


initial begin
  intA = -4'd12;
  regA = intA / 3; // expression result is -4,intA is an integer data type, regA is 65532
  if (regA !=65532 ) $display("Fail1");
  regA = -4'd12; // regA is 65524
  if (regA !=65524) $display("Fail2");
  intA = regA / 3; // expression result is 21841
  if (intA !=21841) $display("Fail3");
  intA = -4'd12 / 3;// expression result is 1431655761. -4’d12 is effectively a 32-bit reg data type
  if (intA !=1431655761) $display("Fail4");

  regA = -12 / 3; // expression result is -4, -12 is effectively an integer data type. regA is 65532
  if (regA !=65532) $display("Fail5");
  regS = -12 / 3; // expression result is -4. regS is a signed reg
  if (regS !=-4) $display("Fail6");
  regS = -4'sd12 / 3;// expression result is 1. -4’sd12 is actually 4. The rules for integer division yield 4/3==1
  if (regS !=1) $display("Fail7");
end

8.3.4 <<< >>>について(Verilog2001)

 算術シフト演算子 <<<は、<<と同じです。(アセンブラ表記が違っても、マシンコードが同じであるように) >>>シフト演算子は、第一パラメータがsignedであるときだけ算術シフト動作を行い、unsigned のときは、>>(論理シフト)と同じ動作になります。
なお、Rotational演算子は、Verilogではありません。

<例>

  
  reg [7:0] xu;
   reg signed [7:0] xs;

   initial begin
      xu = 8'b1100_0000;
      xs = 8'b1100_0000;

      xu = xu >>> 3;//xuは、unsignedなので、8'b0001_1000になります。
      xs = xs >>> 3;//xsは、signedなので、8'b1111_1000になります。

      xs = xu >>> 3;//8'b0001_1000になります。LHSに依存しません。
      xu = xs >>> 3;//8'b1111_1000になります。LHSに依存しません。
   end // initial begin

8.3.5 符号のルール(Verilog2001)

   例
   reg [15:0] a;
   reg signed [7:0] b;
   initial
     a = b[7:0]; // b[7:0] は、 unsigned パートセレクトよって、unsignedなのでゼロ拡張される。

     Realを含んだら、結果はReal
     Unsigngedを含んだら、結果はunsigned
     全てのオペランドがsignedなら、signedになります。ただし、前述ルールが優先されます。         

  Note:

符号付と符号なしの違い
 乗算で見ましょう。ソースです。

`define DIFF_CHECK
module signed_mul_test;
        parameter integer width=3;
        parameter integer mul_width=width*2;
        integer i,j;
        reg signed [width-1:0] as,bs;
        reg [width-1:0] a,b;
        reg [mul_width-1:0] mul;
        reg  signed [mul_width-1:0] muls;
        wire  [mul_width-1:0] mulw=a*b;
        wire signed [mul_width-1:0] mulws=as*bs;

        initial begin
                for (i=0;i<2**width-1;i=i+1) begin
                        a=i;
                        as=i;
                        for (j=0;j<2**width-1;j=j+1) begin
                                b=j;
                                bs=j;
                                mul=a*b;
                                muls=as*bs;
                                                        
                                #10;
                                `ifdef DIFF_CHECK
                                        if (mul !=muls) begin
                                
                                                $display("Unsigned a =%d[%b] b =%d[%b] mul =%d[%b] ",a,a,b,b,mul,mul);
                                                $display("Signed    as=%d[%b] bs=%d[%b] muls=%d[%b] ",as,as,bs,bs,muls,muls);
                                                $display("");
                                        end
                                `endif
                                if (mul !=mulw) $display("Fail");
                                if (muls !=mulws) $display("Fail");
                        end
                end

        end

endmodule

実行結果です。

F:\regression_test\signed_mul_test.v(2)::signed_mul_test
Verilogのシミュレーションの準備が完了しました。スタートは,Goボタンを押してください。
------------- シミュレーションを開始します。--------------------

Unsigned a =1[001] b =4[100] mul = 4[000100]
Signed as= 1[001] bs=-4[100] muls= -4[111100]

Unsigned a =1[001] b =5[101] mul = 5[000101]
Signed as= 1[001] bs=-3[101] muls= -3[111101]

Unsigned a =1[001] b =6[110] mul = 6[000110]
Signed as= 1[001] bs=-2[110] muls= -2[111110]

Unsigned a =2[010] b =4[100] mul = 8[001000]
Signed as= 2[010] bs=-4[100] muls= -8[111000]

Unsigned a =2[010] b =5[101] mul =10[001010]
Signed as= 2[010] bs=-3[101] muls= -6[111010]

Unsigned a =2[010] b =6[110] mul =12[001100]
Signed as= 2[010] bs=-2[110] muls= -4[111100]

Unsigned a =3[011] b =4[100] mul =12[001100]
Signed as= 3[011] bs=-4[100] muls=-12[110100]

Unsigned a =3[011] b =5[101] mul =15[001111]
Signed as= 3[011] bs=-3[101] muls= -9[110111]

Unsigned a =3[011] b =6[110] mul =18[010010]
Signed as= 3[011] bs=-2[110] muls= -6[111010]

Unsigned a =4[100] b =1[001] mul = 4[000100]
Signed as=-4[100] bs= 1[001] muls= -4[111100]

Unsigned a =4[100] b =2[010] mul = 8[001000]
Signed as=-4[100] bs= 2[010] muls= -8[111000]

Unsigned a =4[100] b =3[011] mul =12[001100]
Signed as=-4[100] bs= 3[011] muls=-12[110100]

Unsigned a =4[100] b =5[101] mul =20[010100]
Signed as=-4[100] bs=-3[101] muls= 12[001100]

Unsigned a =4[100] b =6[110] mul =24[011000]
Signed as=-4[100] bs=-2[110] muls= 8[001000]

Unsigned a =5[101] b =1[001] mul = 5[000101]
Signed as=-3[101] bs= 1[001] muls= -3[111101]

Unsigned a =5[101] b =2[010] mul =10[001010]
Signed as=-3[101] bs= 2[010] muls= -6[111010]

Unsigned a =5[101] b =3[011] mul =15[001111]
Signed as=-3[101] bs= 3[011] muls= -9[110111]

Unsigned a =5[101] b =4[100] mul =20[010100]
Signed as=-3[101] bs=-4[100] muls= 12[001100]

Unsigned a =5[101] b =5[101] mul =25[011001]
Signed as=-3[101] bs=-3[101] muls= 9[001001]

Unsigned a =5[101] b =6[110] mul =30[011110]
Signed as=-3[101] bs=-2[110] muls= 6[000110]

Unsigned a =6[110] b =1[001] mul = 6[000110]
Signed as=-2[110] bs= 1[001] muls= -2[111110]

Unsigned a =6[110] b =2[010] mul =12[001100]
Signed as=-2[110] bs= 2[010] muls= -4[111100]

Unsigned a =6[110] b =3[011] mul =18[010010]
Signed as=-2[110] bs= 3[011] muls= -6[111010]

Unsigned a =6[110] b =4[100] mul =24[011000]
Signed as=-2[110] bs=-4[100] muls= 8[001000]

Unsigned a =6[110] b =5[101] mul =30[011110]
Signed as=-2[110] bs=-3[101] muls= 6[000110]

Unsigned a =6[110] b =6[110] mul =36[100100]
Signed as=-2[110] bs=-2[110] muls= 4[000100]


---------- シミュレーションを終了します。time=490----------

どちらかに、MSB1が立ったとき、符号付と符号なしの結果が違うことがわかります。MSBは、符号ビットですから当たり前ですね。

8.3.6 expressionの評価ステップ

8.3.7 式の評価ステップ

8.3.8 signed expressionにおけるxとzについて(Verilog2001)

   signed を拡張するとき、符号項(msb項)が、xならxが、zならzが拡張されます。 unsignedなら、ゼロが拡張されます。

8.3.9 ビット幅について
 式の代入においては、LHSビット幅も含めて最大のビット幅で評価されます。

<例>

 reg [15:0] a, b; // 16-bit regs
 reg [15:0] sumA; // 16-bit reg
 reg [16:0] sumB; // 17-bit reg

 sumA = a + b; // expression evaluates using 16 bits
 sumB = a + b; // expression evaluates using 17 bits

RHSは、全く同じですが、LHSがそれぞれ、16ビット、17ビットになっているために、下のa+bは、符号なし拡張が行われ

 sumB={1'b0,a} +{1'b0,b};

と等価になります。

ビット幅で注意することがあります。
<例>

reg [15:0] a, b, answer; //
answer = (a + b) >> 1; //うまく動かない??

a+bは、16ビット、answerも16ビットなので、a+bは、16ビット幅で評価されます。したがってOverflowを生じる可能性がありますが、式の評価ビット幅としては、16ビットで評価され、その後、1ビットシフト動作になります。この例の対策として、
 answer = (a + b+0) >> 1; //うまく動くが..
0を追加する手が例示(LRM)されています。デシマル0は、少なくとも32ビット以上であることが保証されます。全体のオペレーションビット幅は、32ビット幅(以上)になります。従ってOverflowすることはない、、となっています。シミュレータ上ではその通りなのですが、論理合成で、必要でないビット幅まで、合成してしまうことが考えられますのでお勧めしません。最初から、Overflowまで考慮したビット幅にするべきでしょう。
たとえば、

 reg [16:0] temp;
 reg  [15:0] answer; 
  temp={1'b0,a}+{1'b0,b};//17bitで式を評価させる。overflow させない。
  answer=temp >>1;//

という答案になります。

注意するべきなのは、LHSとRHSのビット幅が異なるときです。Verilog のルールは、
  • 1)LHSも含めたRHSの最大ビット幅を求める。RHSの全てのOperandが符号付なら符号付演算が選択される
  • 2)1)で求めた最大ビット幅と符号の有無で演算
  • 3)演算結果の代入 LHS のビット幅がRHSのビット幅より小さいときMSB SIDEが切り捨てられます。

VHDLなら、LHSとRHSが一致しないとコンパイルエラーになりますが、Verilogではエラーになりません。バグの温床になりえるのでできる限りLHSとRHSのビット幅を一致させて書く方が望ましいと思います。Lintツール(VeritakのLint オプション)でCheckするのも方法の一つです。
 



8.3.9.1 SelfDetermined ビット幅

 上記の例は、LHSまで含めた最大ビット幅で評価されましたが、代入がない場合、たとえば、$display("%b",a&b)の a&b項は、SelfDeterminedのビット幅になります。SelfDeterminedビット幅は次の規則により決定されます。

Expression Bit length 備考
Unsized 定数 Integerと同じ幅になります 通常は、32ビット幅ですが、シミュレータの実装によります。もし、32ビット以上のビット幅のexpressionの一部だったら、
MSBがxならx、zならzが拡張される。そうでなければ(0または1なら、)、sgiendならsigned拡張,unsignedならゼロ拡張がなされる。
Sized定数 Size項で指定される通り
i op j, ここでopは:
+ - * / % & | ^ ^~ ~^
max(L(i),L(j)) Binary Operator
+ - ~ L(i) Unary Operator
i op j, ここで opは
=== !== == != && || >> =< <=
1 bit オペランドは、max(L(i),L(j))
op i,ここで opは、& ~& | ~| ^~ ~ ^ ^~ ! 1 bit Reduction演算、
全てのオペランドは、Selfdetermined
i op j,ここで op は、
>> << ** >>> <<<
L(i) jは、Selfdetermined
i ?j :k max(L(j),L(k)) iは,Selfdetermined
{i,...,j} L(i)+..+L(j) 全てのオペランドは、Selfdetermined
{i{j,..,k}} i * (L(j)+..+L(k)) 全てのオペランドは、Selfdetermined


ここで、L(i)は、オペランドiのビット幅になります。

<例 >

module bitlength();
 reg [3:0] a,b,c;
 reg [4:0] d;

 initial begin
  a = 9;
  b = 8;
  c = 1;
  $display ("answer = %b", c ? (a&b) : d);
 end
endmodule

シミュレータは、 01000と表示しましたか?
a,bのビット幅より、dのビット幅の方が大きいですから、5ビット幅になります。従ってa&bの演算の前にビット拡張が行われ5ビットで評価される為です。


8.4 Ternary Operator
 a ? b : c で、aがxやzだった場合はどうなるのでしょうか?
それは、下表になります。両方共、0/1でなかったら、残り全てのケースでxになります。

? 0 1 x z
0 0 x x x
1 x 1 x x
x x x x x
z x x x x