des00 25 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба чот уж действительно народу заняться, на самоизоляции, нечем, как основы языка, описанные в двух книгах, изучаемые за неделю, разжевывать человеку, который полностью игнорирует, разумные советы. Чудеса да и только Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 7 часов назад, one_eight_seven сказал: 1. В интерфейсе эта переменная может быть за пределами таска. (В модуле тоже) 2. Зачем вам неблокирующее присваивание? 1. Хочется внутри и чтобы сохранялась между вызовами таска, который расположен в модуле 2. Не нужно :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 3 19 апреля, 2020 Опубликовано 19 апреля, 2020 (изменено) · Жалоба 33 minutes ago, HardRock said: 1. Хочется внутри и чтобы сохранялась между вызовами таска, который расположен в модуле 2. Не нужно :) 1a. Так пожалуйста, объявляете переменную в модуле, и обращаетесь к ней в таске, который также объявлен в модуле. 1b. Вы можете объявить таск в модуле, а внутри таска - статическую переменную. Но, она будет статической в пределах области видимости модуля, но автоматической в том смысле, что внутри каждого экземпляра этого модуля она будет своя. 2. Так зачем вы его используете? Ну и самое главное - вам далеко ехать до компиляторов-симуляторов? Почему вы не можете взять и попробовать что-то в этом роде? Spoiler task non_module_update(); static int value = 0; value ++; $display("outside of module task : %d", value); endtask module A #(parameter string NAME = "A"); task update (); static int value = 0; value ++; $display("%s : %d", NAME, value); endtask : update task nmu(); non_module_update(); endtask : nmu endmodule : A module test; A #( .NAME("A1") ) a1 (); A #( .NAME("A2") ) a2 (); initial begin a1.update(); a1.update(); a2.update(); a1.nmu(); a1.update(); a2.update(); a2.nmu(); a1.nmu(); end endmodule : test Мне вот для этого нужно инструменты устанавливать, потому что с синтезом я давно не работаю - только с верификацией, но у вас всё установлено - синтезитуйте, помещайте в оперативную память ПЛИС и смотрите, что получается. P.S. Результат выполнения кода выше: Spoiler A1 : 1 A1 : 2 A2 : 1 outside of module task : 1 A1 : 3 A2 : 2 outside of module task : 2 outside of module task : 3 Изменено 19 апреля, 2020 пользователем one_eight_seven Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба К сожалению ваш код не синтезируется. Падает на первом обращении a1.update() ошибкой Цитата Error (10207): Verilog HDL error at pwm.sv(172): can't resolve reference to object "update" В свою очередь такая таска, определенная вне модуля (да и в модуле тоже) task CMD_TEST(ref reset, ref reg[7:0] __MEMORY__[4], input wire [7:0] rx_byte) ; static int channel_id = 0; if (reset) begin channel_id <= rx_byte; reset <= 0; end else begin __MEMORY__[channel_id] <= rx_byte; end endtask не синтезируется с ошибкой Цитата Error (10959): SystemVerilog error at pwm.sv(12): illegal assignment - automatic variables can't have non-blocking assignments указывает на строку "channel_id <= rx_byte;" Если заменить на блокирующее присваивание, то синтезируется, но channel_id не сохраняется между вызовами. Вызываю так: always @(posedge clk) begin ... // --- Execute command SPI_STATE_CMD: begin case (spi_session_cmd) // - Set PWM channel value //SPI_CMD_SET_PWM: CMD_SetPWMChannel(spi_session_cmd_reset, spi_rx_buffer); SPI_CMD_GET_PWM: CMD_TEST(spi_session_cmd_reset, __MEMORY__, spi_rx_buffer); endcase end ... end Если channel_id вытащить из таски в модуль, откуда она вызывается - то всё прекрасно работает. 3 часа назад, des00 сказал: Вот уж действительно народу заняться, на самоизоляция, нечем, как основы языка, описанные в двух книгах, ищучаемые за неделю, разжевывать человеку, который полностью игнорирует, разумные советы. Чудеса да и только Интернет есть, изучил книги, в том числе цикл статей от iosifk. Делаю как "должно быть", но оно не работает. Для меня это выглядит как глюк. Либо есть какие-то неявные ограничения, либо какой-то момент упустил. Использую Quartus Prime 19.11 Lite, синтезирую под Cyclone IV EP4CE6E22C8, язык SystemVerilog HDL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 3 19 апреля, 2020 Опубликовано 19 апреля, 2020 (изменено) · Жалоба 6 minutes ago, HardRock said: К сожалению ваш код не синтезируется. Это потому что он несинтезируемый. Это концепт, показывающий, как работает static для переменных, объявленных в тасках, и почему они всё-таки automatic. Как вы этот код затянули к себе - это и вовсе тайна, покрытая медным тазом, но синтезируете вы не мой код: У меня просто нет 172 строки. Если нужно синтезируемое, то никаких печатей, никаких string'ов, никаких int'ов - выводите значение из task'ов в output аргументы. Сделайте счётчик типа logic[WIDTH-1:0], его значение смотрите на вейвформах. Ну и ещё... Так и непонятно, чем вас не устраивает нормальный и работающий вариант, который у вас уже получился? Это нормально - использовать в task'ах то, что объявлено за их пределами. Изменено 19 апреля, 2020 пользователем one_eight_seven Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 3 минуты назад, HardRock сказал: Интернет есть, изучил книги, в том числе цикл статей от iosifk. Делаю как "должно быть", но оно не работает. Для меня это выглядит как глюк. Либо есть какие-то неявные ограничения, либо какой-то момент упустил. Использую Quartus Prime 19.11 Lite, синтезирую под Cyclone IV EP4CE6E22C8, язык SystemVerilog HDL. Когда Вам говорят как правильно делать Вы все советы игнорируете. Так-что Вы не просто пропустили какие-то важные моменты. Вы их просто проигнорировали. Единственное что Вы делаете - бездумно копируете чужой код в свой проект в надежде что заработает. При этом Вы совсем не знаете языка на котором пишите. Вы потратили кучу времени, но как говорил Иван Андреевич Крылов : "А воз и ныне там". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 16 минут назад, one_eight_seven сказал: Как вы этот код затянули к себе - это и вовсе тайна, покрытая медным тазом, Ну как, копипастой, но не 1 в 1, всетаки не настолько тупой :D Вот если завернуть в интерфейс interface TestCommand; reg [7:0] channel_id = 0; task run(ref reset, ref reg [7:0] __MEMORY__[4], input wire [7:0] rx_byte); if (reset) begin channel_id <= rx_byte; reset <= 0; end else begin __MEMORY__[channel_id] <= rx_byte; end endtask endinterface и потом вызывать, то всё работает. Но выглядит как костыль немного. Хотя работает и такой вариант меня устроит. Но тема почему не работают стает статик - остаётся открытой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 3 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 10 minutes ago, HardRock said: Но выглядит как костыль немного. Но это потому что вы сделали это как костыль. Интерфейс должен включать в себя всё, что нужно. А так, как вы делаете - ни таски ни интерфейсы не нужны. Вы всё-равно не делаете то, что декларировали, и не достигаете тех целей. которые декларировали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 11 минут назад, Flip-fl0p сказал: Когда Вам говорят как правильно делать Вы все советы игнорируете. Так-что Вы не просто пропустили какие-то важные моменты. Вы их просто проигнорировали. Единственное что Вы делаете - бездумно копируете чужой код в свой проект в надежде что заработает. При этом Вы совсем не знаете языка на котором пишите. Вы потратили кучу времени, но как говорил Иван Андреевич Крылов : "А воз и ныне там". Впервые близко этот язык увидел в прошлую среду. Так что да, не знаю языка на котором пишу, это правда. Только изучаю. И кстати ни одной копипасты, даже когда разбираю примеры из интернета, то переписываю почти всегда с модификациями, но сохранением подхода. Воз тоже разгоняется ударными темпами и без копипасты. Начал с мигания светодиодом, теперь N светодиодов меняют яркость с управлением по SPI с протоколом обмена. Сидеть в симуляторе совершенно не хочется, есть настоящая железка. Да посмотрел RTL симуляцию, погонял SignalTap, интересно, но для такого простого проекта не ощущаю необходимость. Вобщем меня интересует информация по различным нюансам, как например со static внутри таска - почему не работает и бест-практис так сказать в разработке, остальное способен расковырять сам. 4 минуты назад, one_eight_seven сказал: Но это потому что вы сделали это как костыль. Интерфейс должен включать в себя всё, что нужно. А так, как вы делаете - ни таски ни интерфейсы не нужны. Вы всё-равно не делаете то, что декларировали, и не достигаете тех целей. которые декларировали. Какие могут быть альтернативы интерфейсу? Классы на сколько понял не синтезируются, дернуть таску из другого модуля нельзя потому что область видимости внутри модуля. Статик переменные в таске не работают хз почему. Выносить все кишки таска в основной модуль не хочу по соображениям архитектуры и чистоты кода. Когда потребуется добавить новую команду SPI, то хочется просто вставить файл в проект и в основном модуле добавить опцию в case. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 3 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 8 minutes ago, HardRock said: Какие могут быть альтернативы интерфейсу? Дело не в интерфейсе, а в том, как вы его используете. У вас просто интерфейс, который не выполняет функцию интерфейса. Он у вас только для инстанциирования одной внутренней переменной. Ну вы теперь ещё для каждого сигнала, который использует или обновляет таск добавьте по интерфейсу, сделаете "луковицу", которая только всё усложняет. Таск - понятно, он, в случае синтеза выступает лишь немногим отличаясь от текстового макро, но интерфейс - это, как и модуль, сущность, созданная для абстракции, а не для обозначения области видимости для переменной. 8 minutes ago, HardRock said: Выносить все кишки таска в основной модуль не хочу по соображениям архитектуры и чистоты кода. Точно? Ведь вы именно это сделали, только спрятали одну переменную в интерфейс, чтобы сложнее было разобраться в паутине тесных связей, которые вы нагородили. В этом случае лучше оставить это в модуле, чтобы оно было хотя бы очевидно. Quote Статик переменные в таске не работают хз почему. Работают, и я выше показал, что работают. Но у вас задача другая. Вы хотите их синтезировать. Например, Inline инициализация статических переменных внутри тасков - несинтзируема (в моём примере оно имено такое). Кроме того, SystemVerilog, Verilog и т.д. - в первую очередь языки для симуляции, а не для синтеза, поэтому, то, что вы хотите синтезировать нужно делать максимально прозрачно, чтобы вы сами могли вообще без вопросов сказать, при каких уровнях на каких линиях (проводах) произойдёт то или иное. Ну и расскажите, как это будет в случае статической переменной, если одновременно будут вызваны несколько тасков, которые изменяют значение этой переменной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 35 минут назад, HardRock сказал: Сидеть в симуляторе совершенно не хочется, есть настоящая железка. Да посмотрел RTL симуляцию, погонял SignalTap, интересно, но для такого простого проекта не ощущаю необходимость. Вот только даже в простых проектах нужен симулятор. Путь разработки примерно такой: Структурная схема --> HDL описание --> modelsim --> временной анализ --> дебаг в реальной железке. Тем более Вы только начали изучать ПЛИС. Вам 100% обязательна работа с симулятором. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 19 апреля, 2020 Опубликовано 19 апреля, 2020 (изменено) · Жалоба one_eight_seven, теперь понятно, в синтезе это является ограничением Выходит ключевое слово interface - это нормально для абстракции, а не только для описания собственно интерфейсов между модулями. 31 минуту назад, one_eight_seven сказал: Ну и расскажите, как это будет в случае статической переменной, если одновременно будут вызваны несколько тасков, которые изменяют значение этой переменной. Нормальным поведением было бы как в "обычных" языках программирования. Если какая-то переменная объявлена в таске как статик, то она имеет область видимости внутри таска, но физически располагается компилятором в глобальном пространстве чтобы обеспечить сохранение значения между отдельными вызовами таска. В "обычных" языках в случае обращения к такой переменной из разных потоков её состояние будет не определено ввиду гонки. Для HDL логично было бы отслеживать такое обращение и выдавать ошибку, как это сделано с присвоением одной переменной в разных блоках always. Однако тут статик неявно становится не статиком. Ну тоесть ожидалось что код: task MyTask(ref value); static reg [8:0] count; count <= value; end Будет расценен компилятором в синтезе как reg [8:0] count; task MyTask(ref value); count <= value; end Но это оказывается не так, и это есть тот нюанс, который либо знаешь либо нет. Потому что компилятор игнорирует слово static и переменная становится reentrant, как без слова static. Более того, если указано слово static, то компилятор начинает считать переменную automatic и запрещает неблокирующее присвоение. Выглядит как бага в компиляторе, честно :D 31 минуту назад, one_eight_seven сказал: Точно? Ведь вы именно это сделали, только спрятали одну переменную в интерфейс, чтобы сложнее было разобраться в паутине тесных связей, которые вы нагородили. В этом случае лучше оставить это в модуле, чтобы оно было хотя бы очевидно. Есть код для примеров и есть код рабочий. Кроме этой переменной в другой команде будет куча переменных, автомат с кучей состояний и тп. Тоесть реализация команды в 99% случаев не является такой тривиальной. И если всё это тащить во внешний модуль, то когда команд будет с десяток, разобраться в модуле будет нереально. А так каждая команда в отдельном файле. Вход у всех одинаков, а в главном файле только case. Пример двух команд из рабочего кода // --- Execute command SPI_STATE_CMD: begin case (spi_session_cmd) // - Get PWM channel value SPI_CMD_SET_PWM: SPI_CMD_getChannelPWM.onReceive(spi_session_cmd_reset, __MEMORY__, spi_rx_buffer); // - Set PWM channel value SPI_CMD_GET_PWM: SPI_CMD_setChannelPWM.onReceive(spi_session_cmd_reset, __MEMORY__, spi_rx_buffer); endcase end Изменено 19 апреля, 2020 пользователем HardRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 3 19 апреля, 2020 Опубликовано 19 апреля, 2020 (изменено) · Жалоба 6 minutes ago, HardRock said: Но это оказывается не так, и это есть тот нюанс, который либо знаешь либо нет Это вообще зависит от синтезатора. В вашем случае нет инициализации статической переменной. Не исключаю, что какой-нибудь Synopsys behavioral compiler сможет это синтезировать. P.S. вы сейчас пользуетесь не языком программирования, а я зыком описания аппаратного обеспечения. Всё-таки есть разница. Изменено 19 апреля, 2020 пользователем one_eight_seven Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrGalaxy 9 19 апреля, 2020 Опубликовано 19 апреля, 2020 · Жалоба 52 минуты назад, HardRock сказал: Сидеть в симуляторе совершенно не хочется, есть настоящая железка. Да посмотрел RTL симуляцию, погонял SignalTap, интересно, но для такого простого проекта не ощущаю необходимость. В реальном железе не всегда можно отследить все ошибки, симуляция необходима. 5 часов назад, des00 сказал: самоизоляция, Какая там самоизоляция... Полторы недели дали отдохнуть дома и вызвали приказом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardRock 0 19 апреля, 2020 Опубликовано 19 апреля, 2020 (изменено) · Жалоба Да капец с этой короношизой одуреть можно столько дома сидеть На удалёнке можно всегда работать, но банально свободно перемещаться нельзя и всё закрыто - это уже перебор Забавно что страны где нет жестких мер - совсем пропали из новостного эфира, например Беларусь. Молодцы, респект им и уважуха, как говорится. Наверно весь этот кипиш не стоит "тех бедолаг, умерших от тяжелых сопутствующих заболеваний, а тут ещё короновирус добавился", как сказал Лукашенко, поддерживаю. Ну да дадно, тема про FPGA. Вобщем воз почти вышел на орбиту. Описал регистры железки пакед структурами, команды будут жить в interface. Всё клёво, всё работает. Осталось реализовать собственно набор команд и другой полезный функционал, например нужно будет ещё ловить UART на вход, парсить его протокол и складывать в регистры железки чтобы потом можно было забрать по SPI или использовать внутри для логики. Но тут уже всё понятно как делать. Ну и в финале развести плату и собрать железку с FPGA и STM32 на борту. Изменено 19 апреля, 2020 пользователем HardRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться