Jump to content

    
Sign in to follow this  
Golikov

Зачем запись вида reg <= reg на verilog?

Recommended Posts

этимология этой записи, это не единичный случай, значит есть какой-то источник...

может какой-то корпоративный стандарт, особенность синтезатора, может кто-то считал что так меньше ошибок....

Share this post


Link to post
Share on other sites
то есть по вашему для записи вида

always @(posedge clk)
   reg <= input;

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

В этой микрокоманде гонок никогда не будет, но если добавить условие, то очень даже возможны. Если, конечно, не применяются определенные схемотехнические ухищрения, одно их которых коммутатор 2 в 1 на входе, а второй способ подавления связан с clock-gating. Оба способа обеспечиваются входом ENA D-триггера, на который и подается микрооперация, т.е. добавленное условие. А какой из них используется определен типом внутренней архитектуры ПЛИС, что может скрываться на уровне HDL. А запись reg <= reg, как по мне, это как раз указание на применение коммутатора (ясно, что коммутатора может и не быть, а есть загружаемая таблица истинности в LUT).

 

 

Share this post


Link to post
Share on other sites
и не будьте так категоричны насчет того что можно использовать только = для комбинаторики, ровно как что можно использовать только <= под клоком. Можно всякое, особенно если знаешь что делаешь:)

Следование этому правилу как я и написал избавляет от потенциальных проблем.

Но мне вот стало интересно, а есть ли хорошее описание, где смешивание или нарушение этого правила будет оправдано?

 

Не говоря про синтез, даже в симуляции во всех вариантах, где я это видел и оно было сделано не так (смешивание) приходилось "обнаруживать" ньюнсы при симуляции в некоторых случаях. Тут как раз было "что знали, что делали", но в конечном итоге всё переписывалось по правильному.

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

 

 

Share this post


Link to post
Share on other sites
А запись reg <= reg, как по мне, это как раз указание на применение коммутатора (ясно, что коммутатора может и не быть, а есть загружаемая таблица истинности в LUT).

Вы понимаете что запись

 

always @(posedge clk)
   if(...)
      a <= in;

и

always @(posedge clk)
  if(....)
      a <= in;
  else
      a <= a;

 

эквивалентны? То есть добавление a<=a ничего вообще не меняет? какой коммутатор? это обычный регистр... это синхронная схема... я что-то не понимаю Вашу мысль...

 

 

Но мне вот стало интересно, а есть ли хорошее описание, где смешивание или нарушение этого правила будет оправдано?

Конечно есть иначе бы это запретили бы на уровне стандартов языка. Но только надо оговориться использовать под одним always @(posedge clk) для одной переменной то блокирующее, то не блокирующее присвоение - это нельзя.. а само по себе бывает очень даже полезно.

 

допусти у вас есть условие готовности символа SymRdy и подтверждение приема ReceiveAck.

оба идут на выход блока. Condition1 - это условие готовности символа, Condition2 - условие сохранения символа

 

output reg SymRdy ;

output reg ReceiveAck;

 

можно написать

always @(posege clk)
   begin
     if(Condition1)
        SymRdy  <= 1'b1;
     if(Condition1 && Condition2)
        ReceiveAck <= 1'b1;
   end

а можно написать

 

always @(posege clk)
   begin
     if(Condition1)
        SymRdy  = 1'b1;
     if(SymRdy && Condition2)
        ReceiveAck <= 1'b1;
   end

 

при достаточно объемных условиях Condition1 такая запись здорово увеличивает читаемость. Не разносит условия в разные части описания, то есть если условия поменялось вы меняете его в 1 месте а не в нескольких, при этом не теряете такта на его обработку. Можно с той же целью вводить временные переменные которые будут принимать значение условия и в том же клоке использоваться для формирования сигналов. Опять же использование конструкций для тестбенчей и симуляций....

Share this post


Link to post
Share on other sites
Можно всякое, особенно если знаешь что делаешь:)

ага, а потом молодёжь, пытающаяся въехать в ЭТО начинает не разобравшись копипастить. Ибо это писал "САМ! Великий и ужасный". Получаем эффект обезьяньей лапы в действии.

не множьте энтропию умышленно.

Share this post


Link to post
Share on other sites
выше я привел пример как это можно использовать....

вы привели пример как делать не надо. совсем не надо так делать.

это плохо читается и ещё хуже понимается. а через полгода при необходимости добавить ещё 1 ветвь условия вы сами на этом споткнётесь.

 

а надо вынести в отдельный always@(posedge clk)-блок.

Share this post


Link to post
Share on other sites
always @(posege clk)
   begin
     if(Condition1)
        SymRdy  <= 1'b1;
     if(Condition1 && Condition2)
        ReceiveAck <= 1'b1;
   end

а можно написать

 

always @(posege clk)
   begin
     if(Condition1)
        SymRdy  = 1'b1;
     if(SymRdy && Condition2)
        ReceiveAck <= 1'b1;
   end

Не убедительно, а для синтезируемого кода такой трюк для большинства будет не приемлем и даже опасен при последующей поддержке и модификации кода.

В этом случае есть более правильное и надежное решение - стараться использовать для каждого сигнала свой always.

Объединение не улучшает читаемость кода тут и как раз ситуация когда лучше не объединять в одном always, а вынести в два разных always, тк условия для выходов независимы.

 

PS Пока писал ответ, тоже самое уже написал другой человек :laughing:

Edited by Kopart

Share this post


Link to post
Share on other sites
вы привели пример как делать не надо. совсем не надо так делать.

это плохо читается и ещё хуже понимается. а через полгода при необходимости добавить ещё 1 ветвь условия вы сами на этом споткнётесь.

Вероятно у меня еще недостаточно опыта чтобы это понять. Может быть придет со временем :)....

 

а надо вынести в отдельный always@(posedge clk)-блок.

тогда у вас одно условие будет написано в 2 местах описания, потенциально есть вероятность изменить одно, но забыть изменить другое. Если же вы хотите условие оставить под одним блоком алвейс, а под другим уже использовать сигнал, то я надеюсь Вы понимаете что это приведет к задержке обработки в 1 такт. Это можно решить ваером, процедурой или функцией, но это переносит описание в отдельную секцию, что не всегда оправдано...

 

 

PS Пока писал ответ, тоже самое уже написал другой человек

И вам я напишу то же самое... Вы просто опишите в 2 блоках схему которая работает точно также... и посмотрим что будет:)...

 

 

а для синтезируемого кода такой трюк для большинства будет не приемлем и даже опасен при последующей поддержке и модификации кода.

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

Share this post


Link to post
Share on other sites
И вам я напишу то же самое... Вы просто опишите в 2 блоках схему которая работает точно также... и посмотрим что будет:)...

Нет. Правильней assign присвоить общее условие и его использовать в двух always.

Не придется два раза менять одной условие, но при этом нет зависимости в коде двух не связанных выходных сигналов.

 

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

Пусть будет мифический страх, но все упрется в вопрос поддерживаемости кода. Чем он проще, тем потом будет самому и другим проще его модифицировать.

Просто такой трюк может потом стоить дополнительного времени на отладку, а может и никогда не сказаться негативно.

Share this post


Link to post
Share on other sites
В этом случае есть более правильное и надежное решение - стараться использовать для каждого сигнала свой always.

+1. В самых лучших IP-ядрах, с которыми работал, так и делалось - одна олвейз конструкция на один триггер, и к нему еще две строки комментариев что этот триггер делает.

 

Существуют определенные даже не правила, а рекомендации по объединению: в общий олвейз блок помещаются регистры с общим клоком и сигналом сброса, либо с общим клоком и вообще без сброса. Компилятору так проще обрабатывать RTL, поскольку он понимает что под общей олвейз конструкцией находятся однотипные триггеры.

Эти рекомендации я видел то ли в доках Synopsys, то ли в статьях SNUG; сейчас искать уже не возьмусь. Безусловно, это - рекомендации, их соблюдать не обязательно, но желательно (чтобы однажды не споткнуться на ровном месте).

 

про учебник неплохо сказано, рекомендую Вам последовать своей рекомендации ;) Если интересно могу пояснить зачем это делают, но это выходит за рамки данного вопроса.

Видите ли, Вы задаете в начале вопросы новичка, а затем выясняется, что ответ вроде бы знаете. Спрашивается, а зачем тогда вообще эта тема? Но я сам 12 лет писал RTL и могу догадаться об ответе. Что тут можно сказать. Маршрут проектирования микросхем включает в себя множество этапов, в которых разработка RTL - один из первых. Но разработчики RTL часто забывают, что конечная цель - микросхема, а RTL - только первый этап из длинного списка. В результате, разработчик не видит за своим кодом конечной схемы, состоящей даже не из транзисторов, а просто из элементов. Как следствие, я за свою практику наблюдал два пути написания RTL-кода: путь, исходящий из представлений о результате всего маршрута проектирования, и путь программиста - воплощение спецификации изделия сразу в виде кода, не думая о схемотехнике. Ваши вопросы - следствие программерского подхода к написанию RTL, отсюда и желание строить эксперименты с конструкциями языка. Опытный же схемотехник вообще не интересуется всякой ересью, а использует только однотипные конструкции, наилучшим образом распознаваемые компилятором (именно компилятором, а лишь затем синтезатором, мэппером и т.д.).

Да, это скучно, но только используя правильные однотипные конструкции можно писать 100% правильно синтезируемый верилог, поскольку конечная цель - схема, а не изящество строк кода. Почему бессмысленно ставить эксперименты с кодом? Потому что современный софт жутко глюкавый, и поддержка сомнительных конструкций языка может быть реализована по разному у разных производителей тулов, и Вашу сомнительную конструкцию надо проверить сначала во всех тулах, прежде чем с уверенностью использовать в проектах. Итого, либо 100% результат и переносимость (независимость от платформы и тулов), либо эксперименты. Третий вариант - от лукавого.

 

Share this post


Link to post
Share on other sites

Очень жалко что люди пишут по 12 лет, а читать так и не умеют или не хотят.

 

Еще раз: я несколько раз встречал рекомендации и видел людей которые пишут reg <= reg; в олвейс блоках под else или в начале на весь блок. Объяснений зачем они это делают у них нет, только что их так учили. Я надеялся найти того кто видел или слышал объяснения этому феномену, чтобы понять откуда пошла такая мода.

 

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

 

 

 

 

Нет. Правильней assign присвоить общее условие и его использовать в двух always.

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

Share this post


Link to post
Share on other sites
Еще раз: я несколько раз встречал рекомендации и видел людей которые пишут reg <= reg; в олвейс блоках под else или в начале на весь блок. Объяснений зачем они это делают у них нет, только что их так учили. Я надеялся найти того кто видел или слышал объяснения этому феномену, чтобы понять откуда пошла такая мода.

Вопрос из серии "на заборе тоже написано". Задумайтесь, кто учил этих людей, и где? В РФ образования в нашей области считайте что нет: преподают одни самоучки без опыта реальных проектов, без опыта разработки САПР, да вообще без опыта (никоим образом не хочу обидеть уважаемых преподавателей: это не их вина, как и в 10-15 летнем отставании страны в области электроники). Поэтому реальный вес имеет инфа только на известных зарубежных сайтах вроде этого: http://www.asic-world.com/examples/verilog/d_ff.html Берите и пользуйтесь. И не будете иметь проблем с синтезом. А кто еще как пишет, или даже учит студентов - да какая разница? Это их проблемы.

Реальность такова, что писать правильно синтезируемый RTL исключительно скучно - достаточно просто использовать всего 3-4 стандартных шаблона на верилоге. А хотите изысков, раскрыть все возможности языка - идите в верификаторы. Собственно, из RTL-кодинга есть два пути дальнейшего профессионального роста - если Вы больше тяготеете к программированию, то лучше свернуть в верификацию, там больше возможностей развернуться. А если Вам ближе схемотехника, то лучше уходить в синтез, STA и далее в бэк енд (впрочем, программировать и там придется не меньше, только не на верилоге, а на tcl). А выдумывать велосипед - новое описание триггера на верилоге .. хмм .. ну, удачи :-)

Share this post


Link to post
Share on other sites
Но мне вот стало интересно, а есть ли хорошее описание, где смешивание или нарушение этого правила будет оправдано?

Например, синтезируемый Верилоговский оператор "for" - если запретить смешивание "=" и "<=" под клоком, "for" нельзя будет использовать под клоком.

Edited by Leka

Share this post


Link to post
Share on other sites
Вы понимаете что запись

 

always @(posedge clk)
   if(...)
      a <= in;

и

always @(posedge clk)
  if(....)
      a <= in;
  else
      a <= a;

 

эквивалентны? То есть добавление a<=a ничего вообще не меняет? какой коммутатор? это обычный регистр... это синхронная схема... я что-то не понимаю Вашу мысль...

Эти различия устраняет транслятор и, возможно, в итоге синтезируется одна и та же схема, но это еще не факт.

А у меня встречный вопрос. Понятно, что сигнал в условии поступает на вход разрешения записи в триггер, а какова по вашему схема его внутренней логики? И еще, как эта схема изменяется для разных семейств ПЛИС? ... Просто, это поможет приблизиться к ответу на вопрос топика "Откуда это идет и зачем это надо?".

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this