2015-01-21 3 views
2

Я пытаюсь реализовать уравнение в VHDL, которое имеет умножение на некоторую константу и дополнение. Уравнение, как показано ниже,Внедрение уравнения в VHDL

y<=-((x*x*x)*0.1666)+(2.5*(x*x))- (21.666*x) + 36.6653; ----error 

я получил ошибку

 HDLCompiler:1731 - found '0' definitions of operator "*", 
    can not determine exact overloaded matching definition for "*". 

юридическое лицо

entity eq1 is 
     Port (x : in signed(15 downto 0); 
       y : out signed (15 downto 0)); 
    end eq1; 

Я попытался с помощью функции RESIZE и х в целое, но это дает ту же ошибку. Должен ли я использовать другой тип данных? x имеет чистые целочисленные значения, такие как 2,4,6.

+0

* Где * возникает ошибка? –

+0

y <= - ((x * x * x) * 0.1666) + (2.5 * (x * x)) - (21.666 * x) + 36.6653; – Raj

+0

Это связано с [найденными «0» определениями оператора «+» в VHDL] (http://stackoverflow.com/questions/26598471/found-0-definitions-of-operator-in-vhdl) –

ответ

3

С x и y имеют вид данных signed, вы можете их размножить. Однако нет размножения с реальным. Даже если бы это было так, результат был бы реальным (не подписанным или целым).

Итак, сначала вам нужно выяснить, что вы хотите (семантика). Затем вы должны добавить типы броска и функции преобразования.

y <= x*x; -- OK 
y <= 0.5 * x; -- not OK 
y <= to_signed(integer(0.5 * real(to_integer(x))),y'length); -- OK 
+0

Во время синтеза реальность не синтезируется. – Raj

+1

В вашем вопросе конкретно не говорится, что вы делали синтез. Вам нужно будет представлять свои «реальные» значения в виде векторов либо с помощью встроенного 'fixed_pkg', если ваши инструменты поддерживают его, либо используют' signed', а также выполняют учетную запись с дробью. – fru1tbat

2

Как указано в found '0' definitions of operator “+” in VHDL, компилятор VHDL не может найти соответствующего оператора для вашей операции, например. умножение x*x. Вероятно, вы хотите использовать numeric_std (см. here), чтобы сделать операторы для signedunsigned).

Но обратите внимание, что VHDL является не языком программирования, а языком аппаратного дизайна. То есть, если ваша долгосрочная цель - переместить код в FPGA или CPLD, эти функции могут не работать больше, потому что они не синтезируются.

Я заявляю об этом, потому что вы станете больше проблем, когда пытаетесь размножаться, например. 0.1666, потому что VHDL обычно не знает о числах с плавающей точкой из коробки.

+0

Я использовал этот пакет также подписанные и неподписанные пакеты. Можем ли мы сделать его синтезируемым, используя некоторое приближение в значении constatn? – Raj

+0

Не поймите меня неправильно, можно делать вычисления с плавающей запятой, но это, безусловно, вводит накладные расходы, и вы должны очень тщательно подумать, как это сделать. Другой вариант - использовать арифметику с фиксированной точкой. –

+0

ОК. Но «*» создает ошибку. Я использовал Numeric_std с подписанными и неподписанными пакетами. – Raj

3

Это еще один случай, когда симуляция перед синтезом может быть удобной. ghdl для случаев указывает, какой "*" оператор находит первое сообщение об ошибке для:

ghdl -a implement.vhdl
implement.vhdl: 12: 21: нет функции объявления для оператора "*"

y <= -((x*x*x) * 0.1666) + (2.5 * (x*x)) - (21.666 * x) + 36.6653; 
---------------^ character position 21, line 12 

выражения с x умножаются оба операнда с типом signed.

(И далее мы также отметим, что комплексное выражение в правой части операции назначения сигнала в конечном итоге будет интерпретировано как значение signed с узким ограничением подтипа при назначении y).

VHDL определяет тип литерала 0.1666, это абстрактный литерал, то есть десятичный литерал или литерал с плавающей точкой (IEEE Std 1076-2008 5.2.5 Типы с плавающей точкой, 5.2.5.1 Общие, пункт 5):

с плавающей точкой литералы являются литералы анонимного предопределенного типа, который называется в универсальный-настоящему стандарту. Другие типы с плавающей точкой не имеют литералов. Однако для каждого типа с плавающей точкой существует неявное преобразование, которое преобразует значение типа universal_real в соответствующее значение (если оно имеется) типа с плавающей запятой (см. 9.3.6).

Там только один предопределенный тип с плавающей точкой в ​​VHDL, см 5.2.5.2, и с плавающей точкой литерал типа универсальный-неявно преобразуется в тип REAL.

9.3.6 Преобразование типа пункт 14 говорит нам:

В некоторых случаях, неявное преобразование типа будет выполняться. Неявное преобразование операнда типа universal_integer другому целочисленному типу или операнду типа universal_real другому типу с плавающей запятой может применяться только в том случае, если операндом является либо числовой литерал, либо атрибут, либо если операнд - это выражение, состоящее из деления значения физического типа на значение того же типа; такой операнд называется конвертируемым универсальным операндом. Неявное преобразование конвертируемого универсального операнда применяется тогда и только тогда, когда самый внутренний полный контекст определяет уникальный (числовой) тип цели для неявного преобразования, и нет никакой юридической интерпретации этого контекста без этого преобразования.

Потому что вы не включили в пакет, содержащий другой тип с плавающей точкой, которая оставляет нас на поиск оператора в "*" умножения с одним операндом типа signed и одного типа REAL, с типом возвращаемого signed (или другого "*" оператор с аргументами противоположного операнда), а VHDL обнаружил 0 из них.

Там нет

function "*" (l: signed; r: REAL) return REAL; 

или

function "*" (l: signed; r: REAL) return signed; 

найден в пакете numeric_std.

Phillipe предлагает один из способов преодолеть это путем преобразования signedx в целое число.

Исторически синтез не охватывает реальный тип, до версии стандарта VHDL вы, вероятно, иметь произвольную точность 2008 года, а в пункте 7 5.2.5 теперь рассказывает нам:

Реализация должна выбрать представление для всех типов с плавающей точкой, за исключением universal_real, которое соответствует либо IEEE Std 754-1985, либо IEEE Std 854-1987; в любом случае для этого выбранного представления требуется минимальный размер представления 64 бит.

И это не поможет нам, если инструмент синтеза не поддерживает типы REAL с плавающей точкой и совместим с -2008.

VHDL имеет пакет float_generic_pkg, представленный в версии 2008 года, который выполняет операции с плавающей запятой, соответствующие синтезу, и совместим с используемыми типами signed путем преобразования в его тип float и из него.

Прежде чем мы предложим нечто столь радикальное, как выполнение всех этих вычислений, как 64-битные числа с плавающей запятой и синтезируем все, что давайте еще раз отметим, что результатом является 16 бит signed, который является типом массива std_ulogic и представляет собой 16-битное целое число.

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

Поскольку вы используете 16-значное знаковое значение для y, существенное значение будет означать разницу, превышающую 1. Перевернутые знаки или неожиданные 0s между этими двумя методами, скорее всего, скажут вам, что существует проблема с высокой точностью.

Я написал небольшую программу на С, чтобы посмотреть на различия и сразу же он говорит нам 16 бит не достаточно, чтобы держать математику:

int16_t x, y, Y; 
int16_t a,b,c,d; 
double A,B,C,D; 

a = x*x*x * 0.1666; 
A = x*x*x * 0.1666; 

b = 2.5 * x*x; 
B = 2.5 * x*x; 

c = 21.666 * x; 
C = 21.666 * x; 

d =  36; 
D = 36.6653; 

y = -(a + b - c + d); 
Y = (int16_t) -(A + B - C + D); 

и выходы для левого большей величины x :

x = -32767, a = 11515, b =  0, c = 10967, y = -584, Y =  0 
x = -32767, A = -178901765.158200, B = 2684190722.500000, C = -709929.822000 
x = -32767 , y = -584 , Y=  0, double = -2505998923.829100 

Первая строка вывода для 16-битных размножается, и вы можете увидеть все три выражения с умножает неверны.

Вторая строка говорит, что double имеет достаточную точность, но Y (- (A + B - C + D)) не вписывается в 16-битное число. И вы не можете излечить это, если размер результата больше, если размер ввода не изменится. Затем цепочка операций становится вопросом выбора лучшего продукта и отслеживания масштаба, что означает, что вы также можете использовать плавающие точки.

Вы могли бы конечно сделать зажим, если это было бы уместно. Двойное значение на третьей строке вывода - это не усеченное значение. Это более отрицательно, чем x'LOW.

Вы также можете сделать зажим в 16-битной области математики, хотя все это говорит о том, что эта математика не имеет смысла в области оборудования, если она не выполнена в плавающей точке.

Итак, если вы пытаетесь решить настоящую математическую проблему в аппаратных средствах, для нее потребуется плавающая точка, вероятно, выполнена с использованием пакета float_generic_pkg и не будет значимо соответствовать 16-битовому результату.