为什么以下Verilog绝对功能失败?

时间:2014-06-22 16:05:01

标签: verilog

我不明白。出于某种原因,<运算符返回0,即使a明显小于0.该函数仅在我使用a[15]检查符号位时才有效。

N = 16;
wire signed [15:0] a;
assign a = -100;

function [N-1:0] abs (input signed [N-1:0] a);
    abs = (a < {N{1'b0}}) ? -a : a;
endfunction

2 个答案:

答案 0 :(得分:4)

问题是{N{1'b0}}是无符号值。当verilog比较无符号和有符号值时,它会将这两个值视为无符号。

以下引用存在于IEE1364-2005(Verilog)§5.1.7和IEEE1800-2012(SystemVerilog)&amp;第11.4.4节。几乎相同的引用在IEEE1364-2001(Verilog)§4.1.7:

  

当关系表达式的一个或两个操作数无符号时,表达式应解释为无符号值之间的比较。如果操作数的位长度不相等,则较小的操作数应该零扩展到较大操作数的大小。

  当两个操作数都被签名时,表达式应被解释为有符号值之间的比较。如果操作数的位长不相等,则较小的操作数应符号扩展为较大操作数的大小。

你需要将unsinged转换为signed,即$signed({N{1'b0}})。或者,您可以查看a的MSB以了解它是否为负数。

parameter N = 16;

wire signed [N-1:0] a;
assign a = -100;

function [N-1:0] abs_old (input signed [N-1:0] a);
  abs_old = (a < {N{1'b0}}) ? -a : a; // unsigned compare
endfunction
  function [N-1:0] abs_new (input signed [N-1:0] a);
  abs_new = (a < $signed({N{1'b0}})) ? -a : a; // signed compare
endfunction
  function [N-1:0] abs_msb (input signed [N-1:0] a);
  abs_msb = (a[N-1]) ? -a : a; // MSB check
endfunction
initial begin
  $strobe("a:%0d abs(old):%0d", a, abs_old(a)); // a:-100 abs(old):65436
  $strobe("a:%0d abs(new):%0d", a, abs_new(a)); // a:-100 abs(new):100
  $strobe("a:%0d abs(msb):%0d", a, abs_msb(a)); // a:-100 abs(msb):100
end

答案 1 :(得分:2)

试试这个:

N = 16;
reg signed [15:0] a;
assign a = -100;

function [N-1:0] abs (input signed [N-1:0] a);
    abs = (a < 0) ? -a : a;
endfunction

我将变量'a'更改为reg,当你在函数中进行比较时,我会与'0'进行比较而不是向量,并且事情按预期工作。