dxp 32 10 февраля, 2015 Опубликовано 10 февраля, 2015 · Жалоба Ага. Об этом помнишь, допустим, первые пятнадцать часов, после того, как всю схему продумал в общем. А потом, когда дело доходит до описания этого места, просто ошибаешься, по забывчивости, и делаешь не то, или просто путаешь с другим участком схемы. Поэтому я сначала описываю все необходимые в схеме основные сигналы, как wire и как reg, а потом это упрощает жизнь. Ну, у меня как-то другой опыт: ничего, кроме неудобств от переобъявления reg/wire, не испытывал. Сейчас почти везде bit, забыл о проблемах. Чего наоборот то? У меня тоже в ассигнах что попроще. А сложная, тяжелая логика, описанная в always, это редкое исключение, такая логика без регистра на выходе - большая редкость. Не вижу противоречий. Триггеры на выходе логики - обычное дело, но кто обязывает их лепить в этом же блоке? Пример про fsm уже привели. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 10 февраля, 2015 Опубликовано 10 февраля, 2015 · Жалоба см. two process fsm coding Отвратный стиль - все время так и тянет использовать следующее состояние автомата в какой то логике, для упрощения описания, что приводит к неоправданно длинным путям и геморроем со времянкой, по причине того, что, как правило, в логике управления различными блоками от автомата часть условий можно сократить, зная особенности работы. Оптимизатор так сам не сделает, так как это не эквивалентное преобразование. Сплошная куча минусов. В проектах в начале своего пути несколько раз использовал такое описание автомата, и по описанной причине пришлось его каждый раз переписывать (и еще пол-проекта из-за завязок на следующие состояния). После чего отказался в принципе, чтобы сразу избегать таких неприятностей. ничего, кроме неудобств от переобъявления reg/wire, не испытывал. Переобъявить - это десять секунд. И синтезатор об этом напомнит. А вот отыскать логическую ошибку, которой могло бы не быть, это может быть целый день и больше. но кто обязывает их лепить в этом же блоке? Никто не обязывает. Собственный опыт подсказывает, что, если не хочешь возиться сутками в поисках багов, или в вычислении, откуда вечно нехватающие 100 пикосекунд вытащить, то надо делать именно так. За редким исключением. ЗЫ Все вышесказанное является сугубо личным мнением, основанным на собственном опыте, и никак не претендует на истину в последней инстанции. Это лишь советы, как заранее избежать лишних проблем. Так сказать, пройденные грабли... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
egorman44 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба Отвратный стиль интересно, а Вы как тогда описываете автоматы ? В одном always блоке ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба В одном always блоке ? Да. Тем более, что разницы нет почти никакой с описанием в двух блоках, кроме убийства второго (регистрового) блока целиком и замены в первом "always @*" на "always @(posedge clk)". Вот, как-то типа такого (половину комментариев убил, ибо нечего им тут делать): always @(posedge clk or posedge reset) if (reset) ddr_fsm <= DDR_WAIT_INIT; else if (fsm_error) // from bad state detector ddr_fsm <= DDR_WAIT_INIT; else case (ddr_fsm) // wait for INIT fsm complete DDR_WAIT_INIT: if (ddr_ini_fsm == DDR_INI_COMPLETE) ddr_fsm <= DDR_WAIT_Toit_1; // Wait for Toit DDR_WAIT_Toit_1: if (dly_end) ddr_fsm <= DDR_STOP; // STOP phase DDR_STOP: if (reinit) ddr_fsm <= DDR_WAIT_INIT; else if (refi_req) ddr_fsm <= bank_active_any ? (pch_ok ? DDR_PRE_REF : DDR_PRE_PRE_REF) : DDR_DO_REF; else if (read_rq || write_rq) if (open_bank) ddr_fsm <= DDR_OPEN_BANK; else if (reopen_bank) ddr_fsm <= pch_ok ? DDR_REOPEN_BANK : DDR_PRE_REOPEN_BANK; else ddr_fsm <= read_rq ? (rw_ok_a ? DDR_READ : DDR_PRE_READ) : (rw_ok_a ? DDR_WRITE : DDR_PRE_WRITE); // Precharge selected bank if reopen needed DDR_PRE_REOPEN_BANK: if (pch_ok) ddr_fsm <= DDR_REOPEN_BANK; DDR_REOPEN_BANK: ddr_fsm <= DDR_WAIT_Trp_3; DDR_WAIT_Trp_3: if (dly_end) ddr_fsm <= DDR_OPEN_BANK; // Open selected bank DDR_OPEN_BANK: ddr_fsm <= DDR_WAIT_Trcd; DDR_WAIT_Trcd: if (dly_end) ddr_fsm <= reading ? (rw_ok_b ? DDR_READ : DDR_PRE_READ) : (rw_ok_b ? DDR_WRITE : DDR_PRE_WRITE); DDR_PRE_READ: if (rw_ok) ddr_fsm <= DDR_READ; DDR_READ: ddr_fsm <= DDR_STOP; DDR_PRE_WRITE: if (rw_ok) ddr_fsm <= DDR_WRITE; DDR_WRITE: ddr_fsm <= DDR_STOP; // Wait if was incomplete wait DDR_PRE_PRE_REF: if (pch_ok) ddr_fsm <= DDR_PRE_REF; // Precharge if opened DDR_PRE_REF: ddr_fsm <= DDR_WAIT_Trp_2; DDR_WAIT_Trp_2: if (dly_end) ddr_fsm <= DDR_DO_REF; // Refresh DDR_DO_REF: ddr_fsm <= DDR_WAIT_Toit_1; endcase Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
FatRobot 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба Ясно. Вся grlib таким вот "отвратным стилем" написана. Отвратный стиль Тем более, что разницы нет почти никакой Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба Ясно. Судя по приведенным цитатам, ничего не ясно. Поясню. Практически нет разницы во внешнем виде описания тела автомата. Зато имеется гигантская разница в возможных последствиях в части недостижения требуемой скорости работы в целом при использовании комбинаторно вычисленного следующего состояния автомата где либо, кроме как для занесения его в регистр, хранящий текущее состояние. Плохой стиль, именно использовать следующее состояние. Поэтому, лучше сразу предупредить все попытки его использования, априори не давая доступа к нему. Вся grlib таким вот "отвратным стилем" написана. Ну это сугубо их проблема. Повторюсь, это мое личное мнение. А о вкусе и цвете можете вести спор, если он Вам интересен. Я привел тот аргумент, почему, пройдя по граблям, я отказался от таких описаний. Некоторые, возможно, еще по ним не ходили. У них все еще впереди. Либо, эти проблемы они решают применением более быстрого/большого кристалла, а не оптимизацией описания, что, тоже, вполне хороший путь, если денег лишних много. А решать это (на примере grlib) приходится пользователям, а не авторам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
egorman44 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба Нахожусь в ступоре :) Когда возник вопрос "а как собственно описывать автомат правильно" , то на просторах интернета нашел "Synthesizable Finite State Machine Design Techniques Using the New SystemVerilog 3.0 Enhancements" от Sunburst Design. Там много всяких техник описано, но про один always блок было упомянуто как о технике которую надо избегать. Зато имеется гигантская разница в возможных последствиях в части недостижения требуемой скорости работы в целом при использовании комбинаторно вычисленного следующего состояния автомата где либо, кроме как для занесения его в регистр, хранящий текущее состояние. Плохой стиль, именно использовать следующее состояние. Поэтому, лучше сразу предупредить все попытки его использования, априори не давая доступа к нему. Да к вроде бы следующее состояние (NEXT) и используется исключительно для определении текущего (STATE), согласно "two always block coding style". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба Да к вроде бы следующее состояние (NEXT) и используется исключительно для определении текущего (STATE), согласно "two always block coding style". Вот об этом и речь. Если она используется исключительно для этого - то да, вопросов не имею. Но, при этом, совершенно непонятно, ради чего писать второй блок. Он полностью излишен, хотя бы, по принципу "бритвы Оккама". А проблема в том, что возникает большой соблазн это следующее состояние использовать отнюдь не исключительно для этого, раз уж такой сигнал имеется... И вот этот соблазн, по моему мнению, следует радикально отрезать хирургическим путем, чтобы избежать описанных мной проблем... Но, если кому-то нравится писать автоматы в двух блоках просто по причине, что так нравится, так я ничего против не имею... Оно же все равно будет как-то работать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба в описании автомата в одном always вижу только проблемы со смешение переходов и работы автомата. Чисто описательной. То есть если автомат в каждом состоянии делает много работы, то его становиться трудно читать, состояния разрастаются и переходы зрительно теряются. Я эту проблему для себя решил taskами, то есть в самом описании автомата у меня переходы и внутри состоянии вызовы тасков. Описание сокращается, зрительный анализ не теряется. ИМХО... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 11 февраля, 2015 Опубликовано 11 февраля, 2015 · Жалоба Я эту проблему для себя решил taskами, Это не эта проблема, не мешайте мух с котлетами. От этого не зависит, выносить регистр, хранящий состояние автомата в отдельный блок, состоящий из одной строчки "fsm <= fsm_next_state", или сделать это сразу в одном блоке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 13 февраля, 2015 Опубликовано 13 февраля, 2015 · Жалоба SM, Вы же пишете про бритву Оккама, радеете за Verilog вместо VHDL, но тут же говорите, что различие wire и reg - это полезно, чтобы не наделать ошибок по невнимательности, т.к. синтезатор всё подскажет. Тогда уж надо перейти к строгой типизации VHDL, там уж точно синтезатор ошибки будет находить. Моё мнение: если уж мы отказались от строгостей VHDL, сказав, что мы будем за свои ошибки отвечать сами, имея преимущество в удобстве написания, то тогда надо за ошибки отвечать самому до конца. Поддерживаю dxp в том, что неудобно лезть в объявление переменных и менять wire на reg. Да, Вы говорите что поменять объявление всего несколько секунд. Но тут всплывают те же тезисы, что и в холиваре между тоннами писанины на VHDL и краткостью Verilog: не сама писанина страшна, это действительно всего несколько лишних нажатий на клавиатуре. Пугает чисто психологический момент (возвращаемся обратно к wire и reg): вот, надо из текущего положения исходника куда-то лезть в его начало, выискивать там этот злополучный сигнал и менять его объявление. А затем возвращаться обратно и искать то положение в тексте, над которым я работал, которое было на экране. В результате даже мысль можно потерять из-за таких переключений внимания. И тогда можно наделать ещё больше неочевидных системных ошибок (которые тоже не обнаруживаются синтезатором как ошибки), чем ошибка в наличии/отсутствии задержки сигнала на такт. По причине неудобства лезть в объявление, чтобы поменять wire на reg у меня одно время был такой стиль написания, что я все сигналы объявлял как reg, а затем комбинаторику описывал в блоках always @*. Затем немножко изменил мнение: мне понравилось, что при использовании wire и assign можно кратко и наглядно выполнить простые мультиплексоры через ? и :, в одну строчку, чтобы не загромождать код блоками олвэйзов. Пришлось ради этого мириться с необходимостью лезть в объявления в случае изменений способа обработки сигнала... У некоторых есть ещё привычка ставить перед сигналом префикс его объявления типа w_my_signal или r_my_signal. Я вот тоже против таких префиксов, т.к. потом при необходимости изменения объявления придётся все сигналы заменять. Пусть и автозаменой. Но я ей не доверяю на 100%, боюсь, что что-то лишнее в общем случае может попасть под паттерн, поэтому стараюсь автозамены не делать либо делать их с подтверждением вручную по каждой замене, анализируя, что же предлагается заменить. А это уже небыстро... К тому же, у некоторых при таком использовании префиксов появляется соблазн использовать их не совсем по назначению. Допустим, есть 2 почти одинаковых по функциям сигнала, пусть называются они одинаково data_valid, но по типу объявлен один как wire, другой как reg, идут они с разных мест: один с комбинационной схемы, другой с триггера. Разработчику нужно их как-то отличать, и он решает отличать их только по префикску, не меняя имени согласно более узкому назначению каждого из сигналов. Затем по прошествии времени возникает (зачастую уже не у автора кода, а у другого, кто этот код поддерживает после увольнения автора и т.п.) желание что-то улучшить, и тот сигнал, который был объявлен как reg, сделать wire-ом. И тут начинается... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 13 февраля, 2015 Опубликовано 13 февраля, 2015 · Жалоба но тут же говорите, что различие wire и reg - это полезно, чтобы не наделать ошибок по невнимательности, т.к. синтезатор всё подскажет. Тогда уж надо перейти к строгой типизации VHDL, там уж точно синтезатор ошибки будет находить. Я, конкретно, за типизацию по электрической сущности объектов. Причем, за такую, которая не требует преобразований типов при их использовании. То есть, не строгую. Но против лишней типизации по арифметическо-логическим признакам, требующим лишних явных преобразований для использования в качестве аргументов в выражениях (пусть бы была хоть сотня типов по этим признакам, но чтобы корректно преобразовывались один к другому автоматически при использовании). Тут необходимый минимум - signed/unsigned, и, пожалуй, все. Да, в верилоге она, типизация по электрической сущности, сделана слегка кривовато. Но что имеем, то имеем... На мой взгляд, как раз, некая минимально необходимая, почти достаточная... Не хватает разделения объектов на, как бы, "latch" и "pure wire". В остальном - нужный минимум. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sobol' 0 13 февраля, 2015 Опубликовано 13 февраля, 2015 · Жалоба позволю себе вмешаться в дискуссию. М.б. стоит объявлять локальные переменные в том месте, где они используются? По счастью верилог это позволяет. Тогда не придется далеко ходить и переключать внимание для изменения типа. А то есть такая секта людей, которые все сущности объявляют в начале описания модуля, как на VHDL))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 13 февраля, 2015 Опубликовано 13 февраля, 2015 · Жалоба М.б. стоит объявлять локальные переменные в том месте, где они используются? Ну да, почему бы и нет... особенно "сугубо местные" wire xxxx = expression, без слова assign. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 13 февраля, 2015 Опубликовано 13 февраля, 2015 · Жалоба да, я тоже "сугубо местные" взялся объявлять рядом, поддерживаю предложение. Но, к сожалению, показанный мной пример вполне применим и для достаточно общих цепей, которые используются много где, поэтому и объявлять их лучше в шапке, а то потом объявление тем более замучаетесь искать. И именно с такими достаточно общими цепями и возникают потом проблемы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться