Perdaculus 0 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба Добрый день. Есть такая задача: на вход модуля поступает массив параметров. Необходимо этот массив обработать и на его основе получить другой массив параметров, который в свою очередь будет использоваться для generate блоков. Обычно, для этого я писал тело функции без входных/выходных сигналов, внутри которой производил расчет. А потом параметру присваивал эту функцию. Для простого примера: function [31:0] calculate_free_gbe ( ); begin calculate_free_gbe = '0; for (int i = 0; i < N_GBE; i++) begin if (FREE_GBE[i] == 1) calculate_free_gbe = calculate_free_gbe + 1; end return calculate_free_gbe; end endfunction parameter N_FREE_GBE = calculate_free_gbe(); Выглядит, как костыль, но на практике все считалось Квартусом перед синтезом и на основе результата уже синтезировалась логика. Но сейчас мне понадобилось вытащить из функции несколько значений (причем разных по размерам) и присвоить их параметрам. Как можно это реализовать? Я попытался сделать выходные сигналы у функции, но вот как их потом присвоить параметру? Может вообще есть какой то другой вариант области в которой можно производить вычисления и создавать новые параметры? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба Приветствую! 29 minutes ago, Perdachillo said: ... вытащить из функции несколько значений ... Несколько функций с одинаковым расчетом и разными переменными для выхода. Чтобы не считать несколько раз одно и тоже то одна функция расчета возвращает структуру, а отдельные функции берут отдельные поля этой структуры. modue #(patameter A=1, B=2, ...) ( ...); ... typedef struct packed { bit [7:0] var_b; int var_a; } st_FUN_t; function st_FUN_t fun_ab (int a, b); fun_ab.var_a = a; fun_ab.var_b = b; endfunction function int fun_a (); st_FUN_t tmp; tmp = fun(A,B); return tmp.a; endfunction function int fun_b (); ... return tmp.var_b; endfunction // ну и по приколу ;) localparam st_FUN_t PAR_AB = fun_ab(A, B); Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба 41 minutes ago, RobFPGA said: Чтобы не считать несколько раз одно и тоже то одна функция расчета возвращает структуру, а отдельные функции берут отдельные поля этой структуры. Вероятность того, что квартус, до 15.1 включительно сложится от такого, гораздо выше 80% %) проверено на себе) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба Приветствую! 8 minutes ago, des00 said: Вероятность того, что квартус, до 15.1 включительно сложится от такого, гораздо выше 80% %) проверено на себе) Значит мне повезло! В Qu 14.1 как раз и использую такое - возврат структуры констант из функции. Но понятное дело сначала проверять такое нужно в синтезаторе на "кошечках". Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба 23 minutes ago, RobFPGA said: Приветствую! Значит мне повезло! В Qu 14.1 как раз и использую такое - возврат структуры констант из функции. Но понятное дело сначала проверять такое нужно в синтезаторе на "кошечках". Удачи! Rob. тут сильно зависит от вложенности, размера и прочего. примеров много, в моей теме про FEC много различных таблиц, после разработки приходилось корчевать, что-то переносить на провода, какие то таблицы редуцировать, где-то делать предрасчет. В LDPC декодере, вообще пришлось делать лайфхак, генарация таблицы в тестбенче в файле и include его же при синтезе. Хотя все банально и просто. трехмерный массив структур. UPD. А при рассчете таблиц полей галуа, в кодеке рида-соломона, квартус подвисал где то минут на 10, симплифай 9. какой-то ложился насмерть (там тоже пришлось применить лайфхак, подсунув готовый файл) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Perdaculus 0 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба 1 час назад, RobFPGA сказал: Несколько функций с одинаковым расчетом и разными переменными для выхода. Чтобы не считать несколько раз одно и тоже то одна функция расчета возвращает структуру, а отдельные функции берут отдельные поля этой структуры. modue #(patameter A=1, B=2, ...) ( ...); ... typedef struct packed { bit [7:0] var_b; int var_a; } st_FUN_t; function st_FUN_t fun_ab (int a, b); fun_ab.var_a = a; fun_ab.var_b = b; endfunction function int fun_a (); st_FUN_t tmp; tmp = fun(A,B); return tmp.a; endfunction function int fun_b (); ... return tmp.var_b; endfunction // ну и по приколу ;) localparam st_FUN_t PAR_AB = fun_ab(A, B); Идею понял, спасибо! Проверил, даже последняя строка работает. Только не очень понял зачем дополнительные функции использовать, если можно написать в конце: parameter A = PAR_AB.var_a; Тогда и функция один раз выполнится и можно несколько значений выцепить. Или нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба Приветствую! 13 minutes ago, Perdachillo said: Проверил, даже последняя строка работает. Только не очень понял зачем дополнительные функции использовать, если можно написать в конце Это было для примера - у меня например такие разные функции возвращают разные константы которые зависят от входных параметра функции в процессе работы модуля, а не только в момент генерации. А сами константы определяются в одном месте в расчетной функции. Хотя тут вам выбирать как удобнее и нагляднее будет. И да - не надо отдельно еще "parameter A = PAR_AB.var_a;." Можно сразу юзать PAR_AB.var_a везде как обычный paramets Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Perdaculus 0 29 октября, 2019 Опубликовано 29 октября, 2019 (изменено) · Жалоба В 24.10.2019 в 16:43, RobFPGA сказал: И да - не надо отдельно еще "parameter A = PAR_AB.var_a;." Можно сразу юзать PAR_AB.var_a везде как обычный paramets Добрый день. Модельсим съел все на ура. А вот Quartus меня захейтил и выдал кучу ошибок. Как оказалось, он считает, что нельзя писать: parameter A = PAR_AB.var_a; -- Error(10742): constant expressions cannot contains a heirarchical Identifier. Поэтому я решил сделать, как вы изначально предложили, через несколько функций. То есть одна рассчитывает структуру, а другие достают определённое значение. Но в результате получил: Error (10192) value for parameter must be constant expression. Если я правильно понял, получилось это потому что структура у меня содержит три массива logic. И соответственно, я в результате параметру присваиваю logic. Или причина в другом? Подскажите пожалуйста, как можно этот момент обойти и все таки рассчитать несколько массивов в одной функции? Изменено 29 октября, 2019 пользователем Perdachillo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 29 октября, 2019 Опубликовано 29 октября, 2019 · Жалоба Приветствую! 5 minutes ago, Perdachillo said: Модельсим съел все на ура. А вот Quartus меня захейтил и выдал кучу ошибок. Ну так предупреждал же On 10/24/2019 at 3:11 PM, RobFPGA said: Но понятное дело сначала проверять такое нужно в синтезаторе на "кошечках". 6 minutes ago, Perdachillo said: Error (10192) value for parameter must be constant expression Вот тут как раз бы и увидеть ваших милых "кошечек" А то можно долго гадать что у вас в коде не так, а на деле может у вас вообще "собачки" какие-нибудь, а не милые кошечки Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Perdaculus 0 29 октября, 2019 Опубликовано 29 октября, 2019 (изменено) · Жалоба 24 минуты назад, RobFPGA сказал: Вот тут как раз бы и увидеть ваших милых "кошечек" А то можно долго гадать что у вас в коде не так, а на деле может у вас вообще "собачки" какие-нибудь, а не милые кошечки Вот они: typedef struct packed { logic [N_INST_A-1:0][31:0] inst_a; logic [N_INST_B-1:0][31:0] inst_b; logic [N_INST_C-1:0][31:0] inst_c; } st_POS; function st_POS bind_position(); logic [N_INST_A-1:0][31:0] inst_a_position_about_inst_x; logic [N_INST_B-1:0][31:0] inst_b_position_about_inst_a; logic [N_INST_C-1:0][31:0] inst_c_position_about_inst_a; logic [31:0] add_inst_a; logic inst_a_find; begin add_inst_a = 0; inst_a_find = 0; for (int i0=0; i0<N_INST_B; i0++) begin inst_a_find = 0; for (int j0=0; j0<N_INST_A; j0++) begin if (inst_a_position_about_inst_x[j0] == POSITION_INST_B[i0]) begin inst_b_position_about_inst_a[i0] = j0; inst_a_find = 1; end end if (inst_a_find == 0) begin inst_b_position_about_inst_a[i0] = add_inst_a; inst_a_position_about_inst_x[add_inst_a] = POSITION_INST_B[i0]; add_inst_a = add_inst_a + 1; end end inst_a_find = 0; for (int i1=0; i1<N_INST_C; i1++) begin inst_a_find = 0; for (int j1=0; j1<N_INST_A; j1++) begin if (inst_a_position_about_inst_x[j1] == POSITION_INST_C[i1]) begin inst_c_position_about_inst_a[i1] = j1; inst_a_find = 1; end end if (inst_a_find == 0) begin inst_c_position_about_inst_a[i1] = add_inst_a; inst_a_position_about_inst_x[add_inst_a] = POSITION_INST_C[i1]; add_inst_a = add_inst_a + 1; end end bind_position.inst_a = inst_a_position_about_inst_x; bind_position.inst_b = inst_b_position_about_inst_a; bind_position.inst_c = inst_c_position_about_inst_a; return bind_position; end endfunction function [N_INST_A-1:0][31:0] fun_get_inst_a_pos(); st_POS pos; pos = bind_position(); return pos.inst_a; endfunction function [N_INST_B-1:0][31:0] fun_get_inst_b_pos(); st_POS pos; pos = bind_position(); return pos.inst_b; endfunction function [N_INST_C-1:0][31:0] fun_inst_c_inst_b_pos(); st_POS pos; pos = bind_position(); return pos.inst_c; endfunction // parameter st_POS POS = bind_position(); parameter [N_INST_A-1:0][31:0] POSITION_INST_A = fun_get_inst_a_pos(); parameter [N_INST_B-1:0][31:0] POSITION_INST_B_ABOUT_INST_A = fun_get_inst_b_pos(); parameter [N_INST_C-1:0][31:0] POSITION_INST_C_ABOUT_INST_A = fun_inst_c_inst_b_pos(); Оперирую по сути только параметрами, входных/выходных аргументов у функций нет.. Кстати Quartus 17.1 Изменено 29 октября, 2019 пользователем Perdachillo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 29 октября, 2019 Опубликовано 29 октября, 2019 · Жалоба неупакованный массив структур сделайте, может поможет. Хотя не, полный код нужен, квартус считает что где то параметр у вас рассчитывается не от параметра. И еще как простой лайфхак, если есть возможность, сделайте ваши параметры проводами. для синтеза оно без разницы, Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Perdaculus 0 29 октября, 2019 Опубликовано 29 октября, 2019 · Жалоба 42 минуты назад, des00 сказал: неупакованный массив структур сделайте, может поможет. Хотя не, полный код нужен, квартус считает что где то параметр у вас рассчитывается не от параметра. И еще как простой лайфхак, если есть возможность, сделайте ваши параметры проводами. для синтеза оно без разницы, Чтобы сделать структуру неупакованной нужно делать массивы внутри неё неупакованными. И, следовательно, функции, которые достают значение из структуры тоже должны быть неупакованными. А функции могут быть неупакованными вообще? Quartus не дал сделать параметры wire. При этом parameter logic [31:0] - работает. Для того чтобы не приводить кучу строк кода, я задал параметры в чистом виде перед объявлением структуры, чтобы исключить тот факт что параметр рассчитывается не от параметра: parameter N_INST_A = 5; parameter N_INST_B = 6; parameter N_INST_C = 2; parameter integer POSITION_INST_B [N_INST_B-1:0] = '{5,4,32'hF01,32'hF00,32'hF00,0}; parameter integer POSITION_INST_C [N_INST_C-1:0] = '{4,32'hF01}; В результате все равно ошибка - value for parameter POSITION_INSTA_A must be constant expressions Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 29 октября, 2019 Опубликовано 29 октября, 2019 · Жалоба 9 minutes ago, Perdachillo said: Quartus не дал сделать параметры wire. При этом parameter logic [31:0] - работает. module tst (input int addr, output int a, b, c); ............... wire [N_INST_A-1:0][31:0] POSITION_INST_A = fun_get_inst_a_pos(); wire [N_INST_B-1:0][31:0] POSITION_INST_B_ABOUT_INST_A = fun_get_inst_b_pos(); wire [N_INST_C-1:0][31:0] POSITION_INST_C_ABOUT_INST_A = fun_inst_c_inst_b_pos(); always_comb begin a = POSITION_INST_A[addr]; b = POSITION_INST_B_ABOUT_INST_A[addr]; c = POSITION_INST_C_ABOUT_INST_A[addr]; end endmodule вот так сработает. а так, слишком сложная генерация таблицы для квартуса. ЗЫ. В ROM это не синтезируется. паттерны не те, не умеет квартус не упакованный многомерный массив в ROM укладывать) . ЗЗЫ. ресурса минимум Quote Estimate of Logic utilization (ALMs needed) Combinational ALUT usage for logic -- 7 input functions -- 6 input functions -- 5 input functions -- 4 input functions -- <=3 input functions Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 29 октября, 2019 Опубликовано 29 октября, 2019 · Жалоба Приветствую! Да у вас тут стая псов function st_POS bind_position(); logic [N_INST_A-1:0][31:0] inst_a_position_about_inst_x; ... for (int i0=0; i0<N_INST_B; i0++) begin inst_a_find = 0; for (int j0=0; j0<N_INST_A; j0++) begin if (inst_a_position_about_inst_x[j0] == POSITION_INST_B[i0]) begin inst_b_position_about_inst_a[i0] = j0; inst_a_find = 1; end end if (inst_a_find == 0) begin inst_b_position_about_inst_a[i0] = add_inst_a; inst_a_position_about_inst_x[add_inst_a] = POSITION_INST_B[i0]; add_inst_a = add_inst_a + 1; end end Сначала используем, а потом кормим присваиваем значение? Вот Qu и гавкает Удачи! Rob Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Perdaculus 0 29 октября, 2019 Опубликовано 29 октября, 2019 (изменено) · Жалоба 56 минут назад, RobFPGA сказал: Сначала используем, а потом кормим присваиваем значение? Вот Qu и гавкает Да действительно вы правы, я обнулил массивы перед этим и, кажется, ошибка ушла.. Я предполагал, что массив будет содержать неопределённые значения 32'dx и постепенно наполнятся. Думал, что неопределённое значение не равно любому другому значению и нет смысла обнулять его в начале. А Quartus видимо считает, что неопределённое значение не может быть constant expressions. Всем спасибо за помощь! Изменено 29 октября, 2019 пользователем Perdachillo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться