Перейти к содержанию
    

Блокирующее присваивание - симуляция отличается от синтеза

Здравствуйте!

Пишу в проекте примерно такой код.

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

Во втором блоке накапливаю полученные аварии.

module main(
  input clk,
  input nrst,
  input [7:0] in_data,
  output [7:0] out_data
);

reg [3:0] brd_err2 = 0;
reg [7:0] brd_err2_cntr = 0;

always @(posedge clk) begin
  if( ~nrst ) begin
    brd_err2_cntr[7:0] <= 0;
  end else begin
    brd_err2_cntr[7:0] <= brd_err2_cntr[7:0] + brd_err2[3] +
                                               brd_err2[2] +
                                               brd_err2[1] +
                                               brd_err2[0];
  end
end

always @(posedge clk) begin
  if( ~nrst ) begin
    brd_err2[3:0] = 0;
  end else begin
    brd_err2[3] = in_data[3] || in_data[2] || in_data[1] || in_data[0];
    brd_err2[2] = in_data[4] || in_data[2] || in_data[1] || in_data[0];
    brd_err2[1] = in_data[5] || in_data[2] || in_data[1] || in_data[0];
    brd_err2[0] = in_data[3] || in_data[1];
  end
end

assign out_data[7:0] = brd_err2_cntr[7:0];

endmodule

При синтезе и для brd_err2, и для brd_err2_cntr создаются регистры, выходы задержаны относительно входов на 2 такта.

А вот на симуляции получаю очень странные результаты, которые, к тому же, меняются при изменении порядка always`ов.

Что можно сделать, чтобы поправить симуляцию?

2019-09-29 17 37 51.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

1 hour ago, pavlovconst said:

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

А зачем?  Замена  "brd_err2... = .." на "brd_err2... <= .."  сделает код всего лишь немного длиннее, но не менее читаемым. И при этом более предсказуемым при симе и синтезе. Вообще применять bloking assigment нужно аккуратно обычно в синтезе его используют для  описания комбинаторики в always @(*) или при вычислении локальных переменных в функциях или в блоках кода begin end.

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Советую почитать вот эту книженцию:

https://www.springer.com/gp/book/9780387717142

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 hours ago, one_eight_seven said:

Спасибо, прочитал

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

one_eight_seven, RobFPGA, Nick_K  Я понимаю, что основной совет - это сделать все присваивания неблокирующими. Всегда тоже так делал. Но вот сейчас столкнулся с ситуацией, когда мне действительно удобнее использовать блокирующее.

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

 

Больше всего я не понимаю, как могут симуляторы и синтезаторы давать различные результаты, если и те, и другие - опираются на один стандарт? Кто виноват в расхождении? Стандарт плохой? Или его имплементации?

Конечная цель разработчика - получить верную синтезированную схему. И симуляцией мы занимаемся опосредованно, чтобы отладить синтез.

А если результаты не совпадают, то зачем вообще заниматься симуляцией?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

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

23 minutes ago, pavlovconst said:

А если результаты не совпадают, то зачем вообще заниматься симуляцией?

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

Ну а зачем заниматься симуляцией? Не знаю :wink:  Если вы уверены что сможете в слепую, без сима, сваять корректную логику дизайна то тогда действительно незачем. Но вот что вы будете делать если работать будет не так как хотелось. Или как доказывать что вы сделали то что вас просили? Лазать Chipscope/SignalTap по чипу? Так не всегда это возможно. Как тогда быть? 

Поэтому делаете дизайн  использую некоторые правила применения конструкций языка. Проверяете результат в симе, а затем и  в железе. И корректируете дизайн (а иногда и правила) так, чтобы поведение сима и дизайна совпадали. 

Удачи! Rob. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, pavlovconst said:

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

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

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

Кстати SystemVerilog и использование always_ff (и так далее) как раз запретят такое применение, с этой точки зрения он более строг, чем чистый Verilog.

Изменено пользователем lexx

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, lexx сказал:

SystemVerilog и использование always_ff (и так далее) как раз запретят такое применение

Ой ли?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 hours ago, pavlovconst said:

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

Ну, читаемость на любителя(зачем в битовых операциях вместо битового используется логическое или...), а вообще, объявите внутри процесса переменную tmp и после всех пертурбаций, присвойте ее значение к "регистру" с помощью неблокирующего присваивания)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, pavlovconst сказал:

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

Потому что для всякого выразительного (или не очень) средства языка есть свой контекст применения. @RobFPGA уже достаточно внятно объяснил, что к чему. Добавлю только, что если хотите понимать, что там "под капотом", почитайте про планировщик виртуальной машины симулятора (по ссылкам выше про это тоже есть), например, тут. Вы увидите, что блокирующие и неблокирующие присваивания обрабатываются в разных стадиях  (регионах событий) цикла планировщика (блокирующие раньше), из-за этого возникают гонки и странное поведение на симуляторе. Синтез имеет другую исполнительную модель - "тру параллел", там гонок в этом смысле нет.

 

Симулятор является мощным инструментом отладки логики дизайна, отказ от его использования резко понижает "потолок" сложности. Но чтобы от инструмента была польза, надо пользоваться им правильно, понимая условности и ограничения метода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 hours ago, pavlovconst said:

Больше всего я не понимаю, как могут симуляторы и синтезаторы давать различные результаты, если и те, и другие - опираются на один стандарт? Кто виноват в расхождении? Стандарт плохой? Или его имплементации?

А ещё любые программы очень часто пишут индусские быдлокодеры со всеми вытекающими. Я, например, натыкался на ситуацию, когда абсолютно верную конструкцию (на VHDL, но не суть) совершенно верно симулировал ModelSim (он вообще меня пока что не подводил ни разу) и совершенно верно синтезировал Xilinx'овый синтезатор для 6-го семейства, а вот Xilinx'овый же, но для 3-го, то ли синтезировал криво, то ли просто выдавал ошибку на пустом месте, уже не помню подробности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

33 minutes ago, SII said:

А ещё любые программы очень часто пишут индусские быдлокодеры со всеми вытекающими

Не стоит все гнать на индусов, этих достаточно по обе стороны. Если продукт прошёл внутреннее тестирование, то дело не в кодинге.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, SII said:

совершенно верно синтезировал Xilinx'овый синтезатор для 6-го семейства, а вот Xilinx'овый же, но для 3-го,

Тут разговор за ISE/PlanAhead и в часности VHDL код под него. Так вот за 5+ лет разработки я таких ядовых приколов навидался на этой связке, что упаси Элон! Там и вправду то ли криворукие пишут, то ли в какой-то момент все поняли, что переход на Vivado неминуем и делали на отъеб*тесь. В любом случае это не показатель и нужно как минимум смотреть годинг гайд для производителя.

Что касается синтезируемости и моделирования SystemVerilog собственно всё было сказано и непридерживание правил описания влечёт за собой всякого рода неожиданное поведение. А сделано это для того, чтобы на симуляции можно было просимулировать процессы, которые  в реальности могли бы возникать только при определённых состояниях кристалла, как метастабильности или неопределённости. С одной стороны это излишнее усложнение стандартов, которым будут пользоваться единицы (для них можно написать отдельные библиотеки), с другой - это мощнейший инструмент, доступный в любой версии. Увы если дать этот инструмент инженеру, не доконца понимающему его возможностей, могут возникнуть непредвиденные симуляции :wink:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, lexx said:

синтезатор предполагает это и адаптирует ваш код

По каким правилам он "адаптирует"? :shok: И как разработчик должен быть уверен, что при очередной перекомпиляции эта адаптация не приведет к другому результату?

6 hours ago, lexx said:

Кстати SystemVerilog и использование always_ff (и так далее) как раз запретят такое применение, с этой точки зрения он более строг, чем чистый Verilog.

Не заметил. Изначально этот код был написан на SV

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...