Vengin 0 8 сентября, 2019 Опубликовано 8 сентября, 2019 · Жалоба Здравствуйте. Нужно создать в Vivado IP Core, чтобы интегрировать его в Block Design и подключать к Zynq. Был неприятно удивлён тем, что не поддерживаются пользовательские функции (к примеру log2 для задания параметра ширины шины). На форуме Xilinx нашёл пару похожих тем (например, ), только вот решения так и не увидел. В основном описываются проблемы "парсера" IP Packager. Но вроде как в том же ug1118 Creating and Packaging Custom IP говорится о поддержке более сложных математических выражений при помощи XPATH функций: Вот только как и где использовать эти функции XPATH? Как ни пытался ничего не получилось. Даже в описываемом примере, как можно в Verilog коде "output [ceil_log2(max_count)-1:0] count;" заменить пользовательскую функцию ceil_log2 на некую XPATH функцию ceiling(log(2, $max_count)), у которой параметр $max_count описывается как в языке Tcl. Как понять фразы: Цитата To convert this function into an expression that the IP packager can use, replace the custom function with XPATH functions. This change does not occur in the HDL because the custom function is still used, but the IP packager uses a different mechanism for calculating the correct value. Может знает кто, как собственно можно использовать эти самые XPATH функции? Или вообще, как кто боролся с кастомизацией параметров для ядер в IP Packager? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 8 сентября, 2019 Опубликовано 8 сентября, 2019 · Жалоба Приветствую! Не совсем понятно где вы хотите использовать XPATH функции? В RTL или в XML при создании IP core. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба Да я никак не могу понять, где их можно использовать, чтобы собственно добиться кастомизации параметоров. Судя по синтаксису это что-то Tcl-образное. Но куда это впихивать - не понятно. В HDL это не лезет. Пробовал вручную модифицировать файл component.xml, генерируемый при создании IP Core, но сходу не получилось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 16 hours ago, Vengin said: Или вообще, как кто боролся с кастомизацией параметров для ядер в IP Packager? Я боролся и вполне себе успешно. Хотя и не всё работает... Но то такое. Что именно Вы хотите сделать? Все функции в конфигурируемом IP ядре работают нормально. Единственный нюанс - у меня всё реализовано в SV, но функции типа $clog2 и встроенные в пакеты, нормально парсятся, а потом выдаётся варнинг, что: [filemgmt 56-99] Vivado Synthesis ignores library specification for Verilog or SystemVerilog files. ["block_mem_primitive.sv"] И работает дальше без каких-то проблем. И что именно нужно в "кастомизации параметров"? Обычно всё можно описать макросами/параметрами и tcl оставить для более сложных задач Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба Вот простейшая VHDL болванка, с которой экспериментировал: LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; USE IEEE.MATH_REAL.ALL; entity top is generic ( DATA_WIDTH : natural := 32; ADDR_WIDTH : natural := natural(ceil(log2(real( DATA_WIDTH )))) ); port( clk : in std_logic; addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); di : in std_logic_vector(DATA_WIDTH-1 downto 0); do : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end top; architecture beh of top is begin D_P: process(clk) begin if rising_edge(clk) then do <= di; end if; end process; end beh; При попытке упаковать это IP Packager выдаёт ошибки в "Customization Parameters": [IP_Flow 19-343] User Parameter 'ADDR_WIDTH (Addr Width)': Default value "natural(ceil(log2(real(DATA_WIDTH))))" does not match format "long" [IP_Flow 19-343] HDL Parameter 'ADDR_WIDTH (Addr Width)': Default value "natural(ceil(log2(real(DATA_WIDTH))))" does not match format "long" Пробовал заменить библиотечную функцию math_real.log2 на самописную, но с тем же результатом. Из вариантов пробовал вручную настраивать параметр ADDR_WIDTH: Т.е. делал ему Dependency=YES, по формуле expr {log($DATA_WIDTH)/log(2)}. Но это не совсем решает проблему, т.к. например параметр Deаfault Value всё равно нужно выставлять вручную. Но вообще проблема в то, что надо вручную набивать формулы. А надо бы, чтобы формулы подхватывались из HDL кода. Дело в том, что есть параметризируемое ядро, с большим количеством настроек. Наборы настроек задаются конфигурационными файлами, которые представляют vhdl package файлы (их десятки разных), в которых эти настройки рассчитываются. В зависимости от конфигурации ядра просто подключается нужный конфигурационный файл, из которого подставляются значения для ядра (в основном через GENERIC параметры). Вот и пытаюсь понять, как это всё впихнуть в IP Packager. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба Приветствую! 31 minutes ago, Vengin said: Но вообще проблема в то, что надо вручную набивать формулы. А вот оно что, теперь понятно Увы автоматический парсер при паковке IP не шибко умный ИИ - он не обучен (пока еще) понимать все разнообразие фантазий которые юзер может придумать. В таком случе можно: a) сделать свой ИИ парсер VHDL который будет разбираться в вашем коде и генерировать tcl для конфигурации IP (или сразу XML). b) просто перенести алгоритм расчета параметров в tcl который конфигурирует корку при добавлении оной в BD c) сделать враппер корки с парой-тройкой основных параметров одним из которых имя файла конфигурации. И потом уже все конфигурировать на уровне RTL. ... Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 20 минут назад, RobFPGA сказал: Приветствую! А вот оно что, теперь понятно Увы автоматический парсер при паковке IP не шибко умный ИИ - он не обучен (пока еще) понимать все разнообразие фантазий которые юзер может придумать. В таком случе можно: a) сделать свой ИИ парсер VHDL который будет разбираться в вашем коде и генерировать tcl для конфигурации IP (или сразу XML). b) просто перенести алгоритм расчета параметров в tcl который конфигурирует корку при добавлении оной в BD c) сделать враппер корки с парой-тройкой основных параметров одним из которых имя файла конфигурации. И потом уже все конфигурировать на уровне RTL. ... Удачи! Rob. Да я уже начинаю задумываться о всевозможных вариантах. Да и речь не о фантазиях, а о вроде как банальных вещах в языке VHDL, которому больше 20 лет (т.е. речь о не о VHDL-2008). Но воощбе пытаюсь понять: 1) Точно нельзя напрямую из HDL кода (если в рассчётах параметров используются только стандарные библиотечные мат функции типа log2)? 2) Возвращаясь к изначальному вопросу в 1-ом сообщении: что за механизм такой функции XPATH и куда его пихать? Потому как когда вручную модифицируется параметр, то рассчёты делаются вроде как по синтаксису TCL (например, для ADDR_WIDTH по формуле expr {log($DATA_WIDTH)/log(2)} ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба А зачем Вам эта вся головная боль? Наличие генерика DATA_WIDTH обосновано полностью, но параметр ADDR_WIDTH - это чисто внутренняя структура. поменяйте в портах ADDR_WIDTH на natural(ceil(log2(real( DATA_WIDTH )))) а в коде сделайте константу ADDR_WIDTH_С а пользуйтесь ею. И не будет проблем и мороки. Иначе ADDR_WIDTH можно нечаянно поменять в топе (особенно в IP коре, особенно нерадивому юзеру) и будут потом проблемы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 4 минуты назад, Nick_K сказал: А зачем Вам эта вся головная боль? Наличие генерика DATA_WIDTH обосновано полностью, но параметр ADDR_WIDTH - это чисто внутренняя структура. поменяйте в портах ADDR_WIDTH на natural(ceil(log2(real( DATA_WIDTH )))) а в коде сделайте константу ADDR_WIDTH_С а пользуйтесь ею. И не будет проблем и мороки. Иначе ADDR_WIDTH можно нечаянно поменять в топе (особенно в IP коре, особенно нерадивому юзеру) и будут потом проблемы Это простой пример для демонстрации проблемы. Как я и говорил в реальности по другому. Параметры рассчитываются в различных конфигурационных package файлах и, в зависимости от конфигурации, подставляются в ядро (в основном в GENERIC верхнего уровня, но не только есть и другие зависимости). Т.е. например на верхнем уровне есть: USE WORK.CFG_PKG01.all; .... generic( GENERIC_PARAMETER1: natural := PARAMETER1_CALCULATED_IN_CFG_PKG01; ) Значение PARAMETER1_CALCULATED_IN_CFG_PKG01 рассчитано в файле CFG_PKG01.vhd (на основе других параметров заданных в этом конфигурационном файле) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 28 минут назад, Nick_K сказал: А зачем Вам эта вся головная боль? Наличие генерика DATA_WIDTH обосновано полностью, но параметр ADDR_WIDTH - это чисто внутренняя структура. поменяйте в портах ADDR_WIDTH на natural(ceil(log2(real( DATA_WIDTH )))) а в коде сделайте константу ADDR_WIDTH_С а пользуйтесь ею. И не будет проблем и мороки. Иначе ADDR_WIDTH можно нечаянно поменять в топе (особенно в IP коре, особенно нерадивому юзеру) и будут потом проблемы Тем более, если даже убрать в Generic ADDR_WIDTH и в явном виде прописать ширину порта: addr : in std_logic_vector(natural(ceil(log2(real( DATA_WIDTH ))))-1 downto 0); проблемы это не решает. Ошибка: [IP_Flow 19-627] Port 'addr': XPath expression failed: Unsupported function call or array usage "real" found in expression "(natural(ceil(log2(real(spirit:decode(id('MODELPARAM_VALUE.DATA_WIDTH')))))) - 1)". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 36 minutes ago, Vengin said: Значение PARAMETER1_CALCULATED_IN_CFG_PKG01 рассчитано в файле CFG_PKG01.vhd (на основе других параметров заданных в этом конфигурационном файле) Я извиняюсь, но это больше похоже на код программиста. Там где куча #define'ов и перепереименований. Не нужно усложнять себе жизнь, не нужны эти дженерики в топ модуле. Замените все значения GENERIC_PARAMETER1 по коду на значение PARAMETER1_CALCULATED_IN_CFG_PKG01 и выкиньте "ещё один ненужный параметр" с кода. Не усложняйте. Генерики в IP ядре нужны только и ТОЛЬКО, чтобы иметь возможность их сконфигурировать вручную ИЛИ для подхвата от других модулей. Если у вас всё вычисляется в пакете и к ним не должно быть доступа извне - тогда уберите их с глаз долой. Либо меняйте архитектуру 12 minutes ago, Vengin said: Тем более, если даже убрать в явном виде Generic ADDR_WIDTH и в явном виде прописать ширину порта Проблема решается не тут. Проблема решается вот тут: А в объявлении порта укажите любое число от "фонаря". Это если очень хочется оставить дженерик Если же всё-же убрать, тогда будет вот так: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 13 минут назад, Nick_K сказал: Я извиняюсь, но это больше похоже на код программиста. Там где куча #define'ов и перепереименований. Не нужно усложнять себе жизнь, не нужны эти дженерики в топ модуле. Замените все значения GENERIC_PARAMETER1 по коду на значение PARAMETER1_CALCULATED_IN_CFG_PKG01 и выкиньте "ещё один ненужный параметр" с кода. Не усложняйте. Генерики в IP ядре нужны только и ТОЛЬКО, чтобы иметь возможность их сконфигурировать вручную ИЛИ для подхвата от других модулей. Если у вас всё вычисляется в пакете и к ним не должно быть доступа извне - тогда уберите их с глаз долой. Либо меняйте архитектуру Гм. Ну я вроде считаю себя программистом. Но вооще это продиктовано ТЗ - есть набор конфигураций, которые корка должна "подхватывать". Но должна быть и возможность её настраивать вручную. И всегда легко сказать "меняйте архитектуру" (хотя я например не вижу на что менять). Как вы себе это представляете, когда проект пишется не один месяц, вдруг всё поменять. Да и не совсем понятен предлагаемый подход: заменить все параметры на рассчитанные фиксированные значения. Т.е. придётся делать N копий версий проекта (по количеству конигурационных файлов), где каждая версия имеет жёстко вбитые в коде константы рассчитанных параметров? И опять таки самое главное. Простая замена GENERIC на непосредственно формулы с мат функциями типа log2 не решает проблемы (т.е. ошибки IP Packager остаются)!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 12 minutes ago, Vengin said: Т.е. придётся делать N копий версий проекта (по количеству конигурационных файлов), где каждая версия имеет жёстко вбитые в коде константы рассчитанных параметров? Зачем? У Вас уже конфигурируется где-то параметр PARAMETER1_CALCULATED_IN_CFG_PKG01. Вот изменяя его где-то там у Вас будет переконфигурироваться всё остальное. Зачем его где-то определить, а потом переприсвоить в параметр? Ведь уже готовое значение Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба 25 минут назад, Nick_K сказал: Зачем? У Вас уже конфигурируется где-то параметр PARAMETER1_CALCULATED_IN_CFG_PKG01. Вот изменяя его где-то там у Вас будет переконфигурироваться всё остальное. Зачем его где-то определить, а потом переприсвоить в параметр? Ведь уже готовое значение Не понимаю. Допустим есть конфигурационный файл с расчётом параметра PAR1: constant PAR1_0: natural := 32; constant PAR1_1: natural := 8; constant PAR1: natural := natural(ceil(log2( PAR1_0/PAR1_1 ))); Я так понимаю, предлагается вместо формулы вставить константу, равную рассчитанному значению: constant PAR1_0: natural := 32; constant PAR1_1: natural := 8; --constant PAR1: natural := natural(ceil(log2( PAR1_0/PAR1_1 ))); constant PAR1: natural := 2; Так что ли? Тогда при любом изменении значений входящих в формулу (PAR1_0, PAR1_0) нужно вручную перерасчитывать PAR1 (и отслеживать это). Это бессмысленная и ненужная работа. Вроде сама идея программирования сводится к автоматизации ручного труда, а не к обратному. Честно говоря, не хочу превращать тему во флуд. Просто пытаюсь решить простую казалось бы проблему. А для этого пытаюсь получить ответ на два простых вопроса: 1) Можно или нельзя напрямую из HDL кода подтягивать параметры, если в рассчётах параметров используются только стандарные библиотечные мат функции типа log2? 2) Возвращаясь к изначальному вопросу в 1-ом сообщении: что за механизм такой функции XPATH и куда его пихать? Потому как когда вручную модифицируется параметр, то рассчёты делаются вроде как по синтаксису TCL (например, для ADDR_WIDTH по формуле expr {log($DATA_WIDTH)/log(2)} ) ----------------------- 2 часа назад, Nick_K сказал: Все функции в конфигурируемом IP ядре работают нормально. Единственный нюанс - у меня всё реализовано в SV, но функции типа $clog2 и встроенные в пакеты, нормально парсятся, а потом выдаётся варнинг, что: [filemgmt 56-99] Vivado Synthesis ignores library specification for Verilog or SystemVerilog files. ["block_mem_primitive.sv"] И работает дальше без каких-то проблем. А в какой Vivado это? Я пытаюсь на 2017.4. Может в версиях постарше постепенно решают проблемы.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 9 сентября, 2019 Опубликовано 9 сентября, 2019 · Жалоба Приветствую! 1 hour ago, Vengin said: Честно говоря, не хочу превращать тему во флуд. Просто пытаюсь решить простую казалось бы проблему. Никто и не пытается флудить - но простую (для вас) проблему надо еще и понять. Из того что я понял - XPATH это некий стандарт описания констант и мат функций при применении которых в HDL паковка последних в IP будет сопровождаться автоматический парсингом. То есть вам в HDL надо переделать математику чтобы она использовала только такие функции. Например такой вариант вашего примера распознается и вычисляется правильно (для шины di) entity tst_xpath is generic ( DATA_WIDTH : natural := 64; ADDR_WIDTH : natural := 32 -- ceiling(log(2,DATA_WIDTH)) ); port( clk : in std_logic; addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); di : in std_logic_vector(ceiling(log(2,DATA_WIDTH))-1 downto 0); do : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end tst_xpath; Но не все так радужно - для GENERIC это почему-то не работает :( Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться