黄金律は次のとおりです。 すべての operands は signedでなければなりません。
Verilog は unsigned の数字に強く傾いているようです。次のいずれかで unsigned 値が得られます。
- 両方の operands が signedでない限り、2 つの operandsでの任意の操作。
- 明示的な "s" 修飾子が使用されていない限り、明示的な base (たとえば 12′d10) で指定された数値)
- bit-selectの結果
- part-selectの結果
- Concatenations
したがって、肝心なのは、 $signed system functionを使用するか、 signed wires と signed registersを定義することです。
たとえば、 signed register を unsigned registerで乗算し、結果を signed 値として扱うには (もちろん)、次のようにします。
reg [15:0] a; // Unsigned
reg signed [15:0] b;
wire signed [16:0] signed_a;
wire signed [31:0] a_mult_b;
assign signed_a = a; // Convert to signed
assign a_mult_b = signed_a * b
signed_a は "a" よりも 1 bit 広いため、常にゼロである sign bitの場所があることに注意してください。この追加の bitがなければ、 aの MSb は signed_a (MSb = most significant bit) では sign bit として扱われていたでしょう。
signed_aの MSb を、"a" だけでなく {1′b0, a} のようなもので明示的に決定する必要があると誤って思われるかもしれません。ただし、 Verilog standard は、数値が signed であるか unsignedであるかを式だけが判断することを明示しています。したがって、左辺はこの問題には影響しません。したがって、"a" は unsigned 値として扱われるため、ゼロで拡張されます。