VHDL не может сопоставить контекст вызова to_unsigned в пользовательской функции

Я использую Quartus Prime Pro.
Я имею дело с функцией как таковой:

library ieee ;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

function round_resize (a : unsigned; b : integer) return unsigned is
  variable c : signed (a'length - 1 downto 0); --problem child
  variable d : signed (b - 1 downto 0);
begin
  c := a + to_signed(2**(b-2), a'length);
  d := to_unsigned(c(c'length-2 downto (c'length-b-1)));
  return d;
end function;

Но я получаю сообщение об ошибке:

Ошибка (13643): ошибка VHDL в файле.vhd (109): не удается определить определение оператора «+» — найдено 0 возможных определений

Поэтому я изменил проблемного ребенка на это:

c := to_unsigned( a + to_signed(2**(b-2), a'length), a'length);

Но я получаю следующую ошибку:

Ошибка (13815): ошибка квалифицированного выражения VHDL в cpmmod.vhd (110): тип to_unsigned, указанный в квалифицированном выражении, должен соответствовать подписанному типу, подразумеваемому для выражения по контексту.

Что еще я могу попробовать сделать эту работу?


person fifamaniac04    schedule 06.07.2017    source источник
comment
Ну, вы могли бы уважать типы, но непонятно, зачем вы все это делаете.   -  person    schedule 07.07.2017
comment
@user1155120 user1155120 Я действительно не понимаю, почему вы не добавляете это в ответ ... вместо этого вы просто ссылаетесь на изображение кода, у которого есть ответ! Зачем прилагать все эти усилия, но все равно отказываться публиковать ответ?   -  person JHBonarius    schedule 07.07.2017


Ответы (2)


Вы пытаетесь добавить беззнаковое значение со знаком. Вы можете преобразовать один из двух, чтобы получить тот же тип переменных, прежде чем добавлять их.

person Nathanael    schedule 07.07.2017

Натаниэль прав.

Чтобы понять, что происходит, нужно разобраться в двух понятиях:

i) операторы в VHDL являются функциями

Когда вы используете оператор, вы действительно вызываете функцию. В пакете numeric_std есть множество определений различных операторов. Например, одним из определений оператора + является

  function "+" (L, R: UNSIGNED) return UNSIGNED;

ii) VHDL использует перегрузку

Если вы заглянете в пакет numeric_std, то увидите множество определений операторов +:

  function "+" (L, R: UNSIGNED) return UNSIGNED;
  function "+" (L, R: SIGNED) return SIGNED;
  function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED;
  function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
  function "+" (L: INTEGER; R: SIGNED) return SIGNED;
  function "+" (L: SIGNED; R: INTEGER) return SIGNED;

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

... и это ваша проблема. Если вы посмотрите на сигнатуры функций оператора + в numeric_std, перечисленных выше, вы увидите, что не определены операторы +, сочетающие типы SIGNED и UNSIGNED. Следовательно, в вашем случае у компилятора нет функции для вызова, и перегрузка не удалась.

Вам нужно тщательно продумать арифметику, которую вы хотите реализовать, а затем преобразовать все в SIGNED или UNSIGNED по своему усмотрению. Это легко сделать с помощью преобразования типов, потому что SIGNED и UNSIGNED являются близко связанными типами (они оба представляют собой массивы std_logic, индексированные целым числом).

person Matthew Taylor    schedule 07.07.2017