黄金法则是: 所有 operands 必须是 signed。
似乎 Verilog 强烈倾向于 unsigned 数字。以下任何一项都会产生 unsigned 值:
- 对两 operands的任何操作,除非两 operands 都是 signed 。
- 使用显式 base 给出的数字(例如 12′d10),除非使用显式“s”修饰符)
- bit-select的结果
- part-select的结果
- Concatenations
所以底线是要么使用 $signed system 函数,要么定义 signed 线和 signed 寄存器。
例如,要将 signed 寄存器与 unsigned 寄存器相乘,将结果视为 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”宽一个比特(bit),所以 sign 比特有一个位置,它总是为零。如果不是因为这个额外的比特(bit), a的 MSb 将被视为 signed_a (MSb = most significant 比特) 中的 sign 比特。
似乎有必要用 {1′b0, a} 之类的东西来明确地确定 signed_a的 MSb ,而不仅仅是“a”。但是, Verilog 标准明确表示只有表达式确定数字是 signed 还是 unsigned。因此,左侧对此事没有影响。因此“a”被视为 unsigned 值,因此扩展为零。