Logic literal

レジスタのビット長がparameterで変更される場合などに、リセット等で全ビットに同じ値を代入するのにどうコーディングするかは結構悩ましい。

Verilog2001までの場合

全ビットに1'b0を代入する場合、代入式の右辺に1'b0を指定すれば、上位ビットには1'b0が代入される。

reg [7:0] r1:

r1 = 1'b0;

全ビットに1'bx/1'bzを代入する場合、代入式の右辺に1'bx/1'bzを指定すれば、上位ビットにはそのビットが代入される。

reg [7:0] r1;

r1 = 1'bx;

全ビットに1'b1を代入する場合、上記までのスタイルは使えない。

以下の例では、LSBに1'b1が、それ以外には1'b0が代入されてしまう。

reg [7:0] r1;

r1 = 1'b1;

一応、以下の記述で期待通りに動作することは確認しているのだが、トリッキーだし、LRMで動作保障されているのかいまいち読み取れないので、お勧めはしない。

reg [7:0] r1;

r1 = -1'b1

少し汚いが、予想される最大のビット長を代入するのが現実解だと思う。

reg ['width - 1 :0] r1;

r1 = 40'hff_ffff_ffff;

SystemVerilogの場合

LRMの「2.3 Integer and logic literals」に記載されているように、サイズ指定無しのlogicリテラルが用意されている。

全ビット0の場合'0

全ビット1の場合'1

全ビットxの場合'x

全ビットzの場合'z

というように、全て同じスタイルでレジスタに定数を代入することが可能になった。

module test();

reg [39:0] r1;

initial begin

$display("r1 = %x", r1);

r1 = '0;

$display("r1 = %x", r1);

r1 = 'x;

$display("r1 = %x", r1);

r1 = 'z;

$display("r1 = %x", r1);

r1 = '1;

$display("r1 = %x", r1);

end

endmodule // test

# 6.5e

# vsim -do {run -all; quit} -c test

# Loading sv_std.std

# Loading work.test

# run -all

# r1 = xxxxxxxxxx

# r1 = 0000000000

# r1 = xxxxxxxxxx

# r1 = zzzzzzzzzz

# r1 = ffffffffff

# quit

この記述スタイルは代入だけではなくて、比較にも使える。特にデータ幅をパラメータにした時の、ALL1との比較に有用だ。

以下のように、データ幅をパラメータ化した場合、verilog 2001までは、データが最大値となるALL1との比較でポータビリティーのある記述方法が存在しなかった よく考えたら、以下の例の場合はリダクション演算if (&d)で同じことができた。

module #(parameter DWIDTH = 8) test();

reg [DWIDTH - 1 : 0] d;

always_comb begin

if (d == '1) //Compare to All 1

do_some_function();

...