为什么内联Verilog算术移位会将其转换为逻辑移位?

为什么内联Verilog算术移位会将其转换为逻辑移位?,verilog,bit-shift,Verilog,Bit Shift,我读过关于如何在Verilog中实现算术移位的文章。所有人都建议使用$signed(…)>>… 当直接将结果指定给导线或寄存器时,此功能有效,但当将其用作更大表达式的一部分时,则不起作用。即: reg[2:0]a=$signed(3'b100)>>1生成3'b110 reg[2:0]a=1'b1$签署(3'b100)>>>1:3'b000产生3'b010 解决方案似乎是将计算包装成$unsigned: reg[2:0]a=$unsigned($signed(3'b100)>>1)生成3'b

我读过关于如何在Verilog中实现算术移位的文章。所有人都建议使用
$signed(…)>>…

当直接将结果指定给导线或寄存器时,此功能有效,但当将其用作更大表达式的一部分时,则不起作用。即:

  • reg[2:0]a=$signed(3'b100)>>1生成
    3'b110
  • reg[2:0]a=1'b1$签署(3'b100)>>>1:3'b000产生
    3'b010
解决方案似乎是将计算包装成
$unsigned

  • reg[2:0]a=$unsigned($signed(3'b100)>>1)生成
    3'b110
  • reg[2:0]a=1'b1$未签名($signed(3'b100)>>>1):3'b000生成
    3'b110
为什么内联算术移位会使它像逻辑移位一样,为什么在其周围添加
$unsigned
可以解决问题?

下面是一个简单的工作示例:

module puzzle();
   reg [2:0] a_u = 3'b100 >>> 1; // 3'b010
   reg [2:0] a_s = $signed(3'b100) >>> 1; // 3'b110
   reg [2:0] a_mux = 1'b1 ? $signed(3'b100) >>> 1 : 3'b000; // 3'b010

   reg [2:0] b_u = $unsigned(3'b100 >>> 1); // 3'b010
   reg [2:0] b_s = $unsigned($signed(3'b100) >>> 1); // 3'b110
   reg [2:0] b_mux = 1'b1 ? $unsigned($signed(3'b100) >>> 1) : 3'b000; // 3'b110

   initial begin
      $display("a_u = 3'b%3b", a_u);
      $display("a_s = 3'b%3b", a_s);
      $display("a_mux = 3'b%3b", a_mux);

      $display("b_u = 3'b%3b", b_u);
      $display("b_s = 3'b%3b", b_s);
      $display("b_mux = 3'b%3b", b_mux);
   end
endmodule
输出:

a_u = 3'b010
a_s = 3'b110
a_mux = 3'b010
b_u = 3'b010
b_s = 3'b110
b_mux = 3'b110

我不知道原因,但将
3'b000
转换为
3'sb000
似乎也能解决您的问题

reg [2:0] a_mux = 1'b1 ? $signed(3'b100) >>> 1 : 3'sb000;
此外,使用
$signed()
代替
$unsigned()
也可以:

reg [2:0] b_mux = 1'b1 ? $signed($signed(3'b100) >>> 1) : 3'b000;

这里有两条Verilog表达式规则:

  • 语境决定的与自我决定的表达
  • 在上下文中,混合使用有符号和无符号操作数会导致所有操作数都无符号
当你有了这个表情

C ? A : B
操作数
A
B
相互关联。每个操作数的大小都将调整为最大操作数,并且两个操作数都必须经过签名才能保持有符号。这发生在编译期间应用运算符之前
S
是自定的,任何
C
之外的内容都不会对其大小或签名产生任何影响。而且,
C
A
B

类似地,当你有表达式

A >>> S
A
是上下文确定的,
S
是自确定的

现在,如果我们将这两个表达式合并为一个:

C ? A >>> S : B

由于
A
B
在相同的上下文中,并且
B
是无符号的,
A
被转换为无符号的。只要在函数调用中包装
A>>>S
(任何类型的函数调用都是一样的),函数的每个输入参数都有自己的上下文,独立于它所属的表达式的其余部分。返回值将与表达式的其余部分一起在上下文中处理

太棒了,谢谢!有没有一种更干净的方法可以让表达式在自己的上下文中使用,而不是使用
$unsigned
?我不认为它是干净的,但是使用串联可以减少字符数<代码>1'b1?{3'sb100)>>>1}:3'b000
。串联中的所有操作数都是自定的。