3.1 組み合わせ回路
3.1 組み合わせ回路
assign文は組み合わせ回路を記述するときに使用します。
組み合わせ回路を表現するためにはDFFを除く基本3要素を使用します。先ずは、これからの表現方法を見てみましょう。
assign 出力信号 = 論理式;
assign、出力信号名、等号、論理式、最後にセミコロンで終了します。複数行にわたって記述する事が出来ます。
2入力XORの例を再び見てみます。
assign O = (IN_A & ~IN_B) | (~IN_A & IN_B);
ここで、Oは出力信号、(IN_A & ~IN_B) | (~IN_A & IN_B)の部分が論理式です。算術演算の順序等を指定するためにカッコを使用する事が出来ます。先に複数行で記述しても良いと書きましたが、以下の様に記述しても構いません。
assign O = (IN_A & ~IN_B) | (~IN_A & IN_B);
分かりやすく書く工夫をしてみてください。
論理式で使用する事が出来る演算子の中から使用頻度が高い物を選んで説明します。
算術演算
演算子 | 意味 |
& | AND(論理積) |
| | OR(論理和) |
~ | NOT(反転) |
^ | XOR(排他的論理和) |
先のXORの例を再び見てみましょう。
assign O = (IN_A & ~IN_B) | (~IN_A & IN_B);
IN_AとIN_BのNOTとのANDとIN_Aの反転とIN_BのANDのORを記述しています。カッコの中の演算が優先されます。演算子には優先順位がありますのでカッコが不要な事がありますが、慣れるまでは分かりやすさを優先して大袈裟にカッコを付ける事を勧めておきます。
先の演算子の表中にXORがありますので、先の例は以下のように簡単に書く事が出来ます。
assign O = IN_A ^ IN_B;
3項演算子
セレクター、マルチプレクサを記述する時に便利な3項演算子を説明します。
2つの入力A,Bを選択信号Sにより選択するセレクター回路を考えます。
この回路をVerilog-HDLで記述するには下の様に書きます。
assign O = (S ? B : A);
見やすくするために括弧を入れましたが、無くても大丈夫です。
この一行でセレクタを表現する事が出来ます。次に説明するマルチビット表現と組み合わせてデータバス選択回路として使用されます。
マルチビット表現
信号は識別子を使用しますが、マルチビット表現を使用する事が出来ます。デジタル回路では値を表現するために複数本の信号を一つの値をとして使用する事があります。例えばアドレスやデータなど。32bitデータは32本で意味をもちます。このような信号を一つずつ定義する事は大変ですし分かりにくくなるので下の様に一つの識別子で表現する事が出来ます。
次にマルチビット表現を使用したモジュール例を見てみましょう。
/* マルチビット表現の例です */ module DECODER( ADDRESS , // in : Input , Address[7:0] CE // out : Output , Chip enable[1:0] ); // ----- input/ output ----- input [7:0] ADDRESS ; output [1:0] CE ; //------------------------------------------------------------------------------ // Address decoder //------------------------------------------------------------------------------ wire [1:0] CE ; // 組み合わせ回路の出力はwireで定義する assign CE[0] = (ADDRESS[7:0]==8'h0); assign CE[1] = (ADDRESS[7:0]==8'h1); endmodule
ポートリスト
マルチビットになってもポートリストは変更ありません。この部分はあくまで信号名を記述します。
ポート宣言
input [7:0] ADDRESS ; output [1:0] CE ;
入出力定義と信号名の間に[u:l]形式でビット範囲を指定します。[u:l]はビット範囲を表しています。左側uをMSBにコロンで区切って右側lにLSBを書きます。LSB, MSBの値は任意です。
- 補足
- 左にLSBを書く人もいますが、左をMSBにする人が多いと思います。
ここではADDRESSはLSBが0, MSBが7のビット幅8の入力信号、CEはLSBが0, MSBが1のビット幅2の出力信号である事を宣言しています。
内部信号の属性
wire [1:0] CE ; // 組み合わせ回路の出力はwireで定義する
ポート宣言と同じように信号の属性と信号名の間に[u:l]形式でビット範囲を指定します。
回路の記述
assign CE[0] = (ADDRESS[7:0]==8'h0); assign CE[1] = (ADDRESS[7:0]==8'h1);
マルチビット表現の信号は数値として扱う事が多いため、論理演算以外にも上のように等号や不等号など条件抽出を使用する事があります。算術演算も使用する事が出来ます。
条件抽出
使用できる条件抽出
演算子 | 意味 |
= = | 等しい |
!= | 等しくない |
> | 大きい |
< | 小さい |
>= | 大きいまたは等しい |
<= | 小さいまたは等しい |
条件が成立した時に1になります。
assign CE[0] = (ADDRESS[7:0]==8'h0);
この場合、ADDRESS[7:0]が0の時のみCE[0]が1になります。
定義されているLSBとMSBの間の任意の範囲を指定できます。例えば、ADDRESSのビット1から6を抜き出す場合は下のように記述します。
assign CE[0] = (ADDRESS[6:1]==6'h0);
マルチビットとして定義されている信号の中から一つの信号を抜き出して使用するときは下のように書きます。
assign CE[0] = ADDRESS[0];
または
assign CE[0] = (ADDRESS[0]==1'b1);
この場合、ビット0を抜き出しています。
算術演算
演算子 | 意味 |
+ | 加算 |
- | 減算 |
例えば、信号A[7:0]に1を加えて信号O[7:0]に出力する時は下の様に書きます。
wire [7:0] O; assign O[7:0] = A[7:0] + 8'd1;
- 積算、除算、剰余
- 上記以外にも積算、除算、剰余演算子も定義されていますが回路記述に使用する事はほとんどありません。これらの回路規模は大きく、実現方法も数多く存在します。多数の実装方法の中から適した回路を指定するためには、ゲートを想像できる程度の記述をするかゲートレベルで回路が指定されているライブラリを使用する必要があります。
- シミュレーション
- 回路に変換する必要が無いシミュレーションのテストベンチでは積算、除算、剰余演算子を使用した方が高速に動作します。
ビット結合
マルチビット表現された複数の信号まとめて新しいマルチビット表現した信号を定義したい時があります。
例えは、信号Aが[7:0]、信号B[15:0]で定義されている信号を合わせて一つの信号C[23:0]を定義したい時を考えてみます。C[15:0]にB[15:0]を接続し、C[23:16]にA[7:0]を接続します。
下の様に一本ずつ定義すれば問題ない事はわかると思います。
wire [23:0] C; assign C[0] = B[0]; assign C[1] = B[1]; : : : assign C[15] = B[15]; assign C[16] = A[0]; : : : assign C[23] = A[7];
しかし、これは大変です。そこで、下の様に書ける事に気がつくかもしれません。
wire [23:0] C; assign C[ 15:0] = B[15:0]; assign C[23:16] = A[7:0];
これでも良いのですが、一文で書く方法が文法で定義されています。下の様に記述します。
wire [23:0] C; assign C[23:0] = {A[7:0],B[15:0]};
ここでは右辺にのみ使用しましたが、左辺(出力側)でも使用する事が出来ます。
wire [7:0] D; wire [23:0] E; assign {D[23:0],E[7:0]} = {A[7:0],B[15:0]};