UDP (User Defined Primitives) [Verilog]
シミュレーション用の記述としてUDPという方法があります。
入力と出力をテーブル形式で表現した、いわゆる真理値表での記述方法です。
このテーブルの表現にはいくつかのルールがあります。
0, 1 : 論理0または1
x or X : 不定値
- : 出力の変化なし (シーケンシャルUDP)
? : 入力の値は何でも良い (0, 1, または X)
b または B : 入力の値は0か1
(vw) : 入力がvからWへ変化
例: (01) は0から1への変化を示す
r または R : 入力信号の立ち上がり = (01)
f または F : 入力信号の立下り = (10)
p または P : 0からの変化、1への変化 (01), (0X) または (X1)
n または N : 1からの変化、0への変化 (10), (1X) または (X0)
* : あらゆる入力の変化 = (??)
組み合わせ回路のUDP
シーケンシャル回路のUDP
入力と出力をテーブル形式で表現した、いわゆる真理値表での記述方法です。
このテーブルの表現にはいくつかのルールがあります。
0, 1 : 論理0または1
x or X : 不定値
- : 出力の変化なし (シーケンシャルUDP)
? : 入力の値は何でも良い (0, 1, または X)
b または B : 入力の値は0か1
(vw) : 入力がvからWへ変化
例: (01) は0から1への変化を示す
r または R : 入力信号の立ち上がり = (01)
f または F : 入力信号の立下り = (10)
p または P : 0からの変化、1への変化 (01), (0X) または (X1)
n または N : 1からの変化、0への変化 (10), (1X) または (X0)
* : あらゆる入力の変化 = (??)
組み合わせ回路のUDP
primitive mux (y, a, b, sel);
output y;
input sel, a, b;
table // primitiveに定義した入力順に一致
// a b sel : y
0 ? 0 : 0; // aを選択; bには依存しない
1 ? 0 : 1; // aを選択; bには依存しない
? 0 1 : 0; // bを選択; aには依存しない
? 1 1 : 1; // bを選択; aには依存しない
endtable
endprimitive
シーケンシャル回路のUDP
primitive dff (q,d,clk,rst);
output q;
input clk, rst, d;
reg q; // 出力はregで定義
initial q = 0; // パワーアップ時の状態
table
// d clk rst:state:q
? ? 0 : ? :0; // リセット(rst)時
0 R 1 : ? :0; // clk立ち上がりでdを出力
1 R 1 : ? :1: // clk立ち上がりでdを出力
? N 1 : ? :-; // clk立下りでqはそのまま
* ? 1 : ? :-; // clkの変化がなければqはそのまま
? ? P : ? :-; // rstの0以外への変化ではqはそのまま
0 (0X) 1 : 0 :-; // clkがXに変化してもqはそのまま
1 (0X) 1 : 1 :-; // clkがXに変化してもqはそのまま
endtable
endprimitive
always [Verilog]
Verilogで組み合わせ回路を記述するとき、一番素直な書き方はwireとassignを使う方法です。少し複雑な条件を見やすく書く場合には、functionを使うか、alwaysを使ってifやcaseで条件を記述します。
このalwaysを使った組み合わせ回路でよくある問題が、alwaysのセンシティビティ・リスト抜けです。センシティビティ・リストとは、
always @( a or b or c )
と書くときのカッコ( )の中の信号リスト a, b, cのことです。組み合わせ回路の中で使っている信号がこの中に書かれていないと、その信号の変化が出力に反映されません。つまり、組み合わせ論理は合っているのに、正しい動作をしないということです。
これを改善したのが、Verilog 2001で採用されたセンシティビティ・リストを省略する書き方です。
always @*
これにより、センシティビティ・リスト抜けという問題はなくなり、記述時の確認作業も軽減されました。
ちなみに、組み合わせ回路をalwaysで記述する場合、信号の宣言はregになります。wireではありません。
SystemVerilog
SystemVerilogでは、さらに3つのalwaysが追加されました。
この記法では、alwaysで記述された回路の意図が明確にわかるようになりました。
always_combは、ほぼalways @*と同じ組み合わせ回路記述用です。
always_ffは、フリップ・フロップを生成するときに使います。
always_latchは、ラッチの生成ですが、現在の設計手法ではほとんど用いられないと思います。
このalwaysを使った組み合わせ回路でよくある問題が、alwaysのセンシティビティ・リスト抜けです。センシティビティ・リストとは、
always @( a or b or c )
と書くときのカッコ( )の中の信号リスト a, b, cのことです。組み合わせ回路の中で使っている信号がこの中に書かれていないと、その信号の変化が出力に反映されません。つまり、組み合わせ論理は合っているのに、正しい動作をしないということです。
これを改善したのが、Verilog 2001で採用されたセンシティビティ・リストを省略する書き方です。
always @*
これにより、センシティビティ・リスト抜けという問題はなくなり、記述時の確認作業も軽減されました。
ちなみに、組み合わせ回路をalwaysで記述する場合、信号の宣言はregになります。wireではありません。
SystemVerilog
SystemVerilogでは、さらに3つのalwaysが追加されました。
- always_comb
- always_ff
- always_latch
この記法では、alwaysで記述された回路の意図が明確にわかるようになりました。
always_combは、ほぼalways @*と同じ組み合わせ回路記述用です。
always_ffは、フリップ・フロップを生成するときに使います。
always_latchは、ラッチの生成ですが、現在の設計手法ではほとんど用いられないと思います。
レジスタのビットを同じ値で埋める [Verilog]
複数ビットのレジスタを、全て同じ値で埋める方法をまとめておきます。
これもいろいろ好みがあるので、好きな書き方を使えばいいと思いますが、SystemVerilogではシンプルに記述できます。
例えば、64ビットのレジスタの全ビットに同じ値を代入する書き方です。
reg [63:0] data;
Verilog
SystemVerilog
これもいろいろ好みがあるので、好きな書き方を使えばいいと思いますが、SystemVerilogではシンプルに記述できます。
例えば、64ビットのレジスタの全ビットに同じ値を代入する書き方です。
reg [63:0] data;
Verilog
data = 0;
data = 'bz;
data = 'bx;
// 以下は全てのビットに'1'を代入
data = 64'hFFFFFFFF_FFFFFFFF;
data = {64{1'b1}};
data = ~0;
data = -1;
SystemVerilog
data = '0;
data = '1;
data = 'z;
data = 'x;