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 | 1 | |
| 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 のルールは、
|
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 |