「8ビット同士を足して9ビットに代入する」を深く考えずに書いた場合の挙動の違いについて。
Verilog
wire[7:0] a;
wire[7:0] b;
wire[8:0] c;
assign c = a + b;
a = 8'b1111_1111
, b = 8'b0000_0001
のとき、c = 9'b1_0000_0000
になります。
Chisel
val a = UInt(width = 8)
val b = UInt(width = 8)
val c = UInt(width = 9)
c := a + b
a = 8'b1111_1111
, b = 8'b0000_0001
のとき、c = 9'b0_0000_0000
になります。
なんで?
VerilogもChiselも、Mビット + Nビットの結果は Max(M,N)ビットなのですが、
Verilogの場合、代入の場合は例外として、左辺のビット数に合わせます。
Chiselはそんなことしません。
コードで示すと、
wire[7:0] a;
wire[7:0] b;
wire[8:0] c;
// assign c = a + b と同じ
assign c = {1'b0, a} + {1'b0, b};
verilogは、ゼロ拡張してから足します。
一方上記ChiselコードのVerilog出力は、
wire[7:0] a;
wire[7:0] b;
wire[8:0] c;
wire[7:0] T0;
assign T0 = a + b;
assign c = {1'h0, T0};
のようになります。(イメージ)
足してから、ゼロ拡張します。
verilogでいうところの、assign c = a + b;
は、Chiselでは
val a = UInt(width = 8)
val b = UInt(width = 8)
val c = UInt(width = 9)
c := Cat(UInt(0), a) + Cat(UInt(0), b)
になります。