Вопрос:

Почему следующая абсолютная функция Verilog не работает?

verilog

3869 просмотра

3 ответа

335 Репутация автора

Я не понимаю По какой-то причине <оператор возвращает 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
Автор: geft Источник Размещён: 22.06.2014 04:05

Ответы (3)


2 плюса

511 Репутация автора

Попробуй это:

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», а не с вектором, и все работает так, как вы ожидаете.

Автор: Ciano Размещён: 22.06.2014 05:00

4 плюса

13439 Репутация автора

Решение

Проблема {N{1'b0}}в неподписанном значении. Когда Verilog сравнивает значение без знака и со знаком, оба значения будут рассматриваться как без знака.

Следующая цитата существует в IEE1364-2005 (Verilog) § 5.1.7 и IEEE1800-2012 (SystemVerilog) & section 11.4.4. Почти идентичная цитата содержится в IEEE1364-2001 (Verilog) § 4.1.7:

Когда один или оба операнда реляционного выражения являются беззнаковыми, выражение должно интерпретироваться как сравнение между беззнаковыми значениями. Если операнды имеют неодинаковую длину в битах, меньший операнд должен быть расширен до нуля до размера большего операнда.

Когда оба операнда подписаны, выражение должно интерпретироваться как сравнение значений со знаком. Если операнды имеют неравные битовые длины, меньший операнд должен быть расширен до знака большего операнда.

Вам нужно забрасывать Беззнаковое как знаковые, то есть $signed({N{1'b0}}). Кроме того, вы можете посмотреть на MSB, aчтобы узнать, если он отрицательный.

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
Автор: Greg Размещён: 22.06.2014 06:10

0 плюса

1 Репутация автора

Альтернатива:

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

assign abs = (a[N-1]) ? -a : a;

Вы можете принять решение о знаке на основе самого значимого бита; это установлено или нет. Достаточно просто, чтобы функция была, вероятно, излишней. Я также использовал ваш параметр N ... который позволяет меньше изменений кода с течением времени.

Автор: JerryJamesO Размещён: 12.03.2019 08:23
Вопросы из категории :
32x32