Jump to content

    
Sign in to follow this  
pavlovconst

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

Recommended Posts

1 minute ago, pavlovconst said:

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

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

Для FPGA можно и так посмотреть, в случае с ASIC есть Formality.

В последнем проекте: ncsim, vivado, dc и Formality, как один пакет (по чипу потом все сошлось) выдавали одно, а вот результат Zebu отличался. Причем это был как SystemVerilog (в чем я еще могу согласится), но и чистый Verilog.

Share this post


Link to post
Share on other sites
3 hours ago, dxp said:

Синтез имеет другую исполнительную модель - "тру параллел", там гонок в этом смысле нет.

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

Share this post


Link to post
Share on other sites

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

1 hour ago, pavlovconst said:

Пока что получается, что синтезатор имплементирует код именно так, как задумал разработчик.

Синтезатор и симулятор выполняют разные задачи. Синтез физической структуры обработки дизайна и симуляция поведения во времени. Отсюда и возможные разные результаты при одном и том же входном коде.  Ну и опять же - чтобы симулятор  правильно отображал реальную действительность модель симуляции должна быть полной. А чисто функциональная симуляция грешит  упрощениями (0 задержки) для ускорения этого процесса. Вот сим и не понял что задумал разработчик. 

 

1 hour ago, lexx said:

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

Как обычно - разработчик делает pots-synthesis/post-P&R симуляцию и сравнивает поведение с функциональной golden reference моделью. Да еще и формальная верификация добавляется. И если вдруг будут разные результаты - то начинает копать, чтобы понять где именно  (в синтезаторе или в симе) он нако... был неправильно понят :unknw:.

Удачи! Rob.

Share this post


Link to post
Share on other sites
1 hour ago, pavlovconst said:

По каким правилам он "адаптирует"?

Насколько мне известно изначально происходит распознавание синтаксических структур и прагм. потом на основе этих данных происходит синтезирование примитивов и элементов, ну а дальше map, place&route.

Чтобы быть уверенным в каждом проходе компиляции достаточно выдерживать одни и те же правила описания (которые описаны в стандарте) и никаких проблем не должно возникнуть (если только вы не перешли на другой, свежий и новый синтезатор - старые игроки обычно не грешат изменением поддержки стандартов)

Share this post


Link to post
Share on other sites
56 minutes ago, RobFPGA said:

Как обычно - разработчик делает pots-synthesis/post-P&R симуляцию и сравнивает поведение с функциональной golden reference моделью.

Симуляция не покрывает, только формальная верификация.

Share this post


Link to post
Share on other sites
8 hours ago, dxp said:

почитайте про планировщик виртуальной машины симулятора (по ссылкам выше про это тоже есть), например, тут

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

Но такой код, с перемешанными блокирующими и неблокирующими присваиваниями, оставлять в проекте мне было бы стыдно. =(

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;
    brd_err2[3: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];
    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

 

2019-09-30 12 34 25.png

Share this post


Link to post
Share on other sites
18 minutes ago, pavlovconst said:

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

Но такой код, с перемешанными блокирующими и неблокирующими присваиваниями, оставлять в проекте мне было бы стыдно. =(

уберите блокирующие. они,  в вашем случае роли не играют абсолютно. так будет не стыдно?

Share this post


Link to post
Share on other sites
6 минут назад, pavlovconst сказал:

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

А почему сразу не сделать это в явном виде.

Ведь Вам дали ссылку на Клиффа:

Guideline: Use blocking assignments in always blocks that are written to generate
combinational logic [1]. 
Guideline: Use nonblocking assignments in always blocks that are written to generate
sequential logic [1]. 

Но Вы это игнорируете...

И еще. Вам действительно надо сделать что-то вроде этого: 

brd_err2[3] = in_data[3] || in_data[2] || in_data[1] || in_data[0];

только за один такт? С какой скоростью в проект "прибывают" данные и какая частота у "clk"? Может быть можно успеть все эти вычисления сделать и по-другому?

А главный вопрос вот какой: какой смысл делать вот так: " Намеренно использую при этом блокирующее присваивание, так код получается коротким и хорошо читаемым."? Если потом приходится более 20-то часов выяснять как преодолеть проблему данного кода. И проблема еще не решена. Потому как если даже Вы заставите программные инструменты сделать "как надо" сегодня, то через полгода-год появится новая версия софта и возможно проблемы выплывет снова. IMXO, за 20 часов можно переделать проект так, чтобы наверняка не было никаких проблем... 

Share this post


Link to post
Share on other sites
25 minutes ago, iosifk said:

А почему сразу не сделать это в явном виде.

ну лень ему писать красиво

always @(posedge clk) begin
  if( ~nrst ) begin
    brd_err2      <= '0;
    brd_err2_cntr <= '0;
  end else begin
    brd_err2[3] <= |{            in_data[3 : 0]};
    brd_err2[2] <= |{in_data[4], in_data[2 : 0]};
    brd_err2[1] <= |{in_data[5], in_data[2 : 0]};
    brd_err2[0] <= |{in_data[3], in_data[1]};
    //
    brd_err2_cntr <= brd_err2_cntr + brd_err2[3] + brd_err2[2] + brd_err2[1] + brd_err2[0];
  end
end

да и обычный декодер флагов это, со счетчиком событий

Share this post


Link to post
Share on other sites

Попробуйте еще добавить задержки в неблокирующие присваивания. Так проще смотреть значения выходов при движении курсора по фронту клока.

Например, так:

`timescale 1ns/100ps

...

 brd_err2_cntr[7:0] <= #1 brd_err2_cntr[7:0] + ...

 

Пишут что это не всегда хорошо. За и против взвешены в этой статье:

http://www.sunburst-design.com/papers/CummingsSNUG2002Boston_NBAwithDelays.pdf

Я пока не сталкивался со случаями, когда бы это вредило.

Share this post


Link to post
Share on other sites
49 minutes ago, des00 said:

ну лень ему писать красиво

des00, Спасибо за "красивый" вариант, но в целевом проекте все несколько сложнее устроено. Поэтому я и пытаюсь дожать вариант с блокирующими.

1 hour ago, iosifk said:

если даже Вы заставите программные инструменты сделать "как надо" сегодня, то через полгода-год появится новая версия софта и возможно проблемы выплывет снова

Порядок обработки событий планировщиком симулятора, описанный в стандарте, поменяется наврядли =)

Share this post


Link to post
Share on other sites
19 minutes ago, pavlovconst said:

des00, Спасибо за "красивый" вариант, но в целевом проекте все несколько сложнее устроено. Поэтому я и пытаюсь дожать вариант с блокирующими.

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

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

Share this post


Link to post
Share on other sites
4 минуты назад, des00 сказал:

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

Я дополню... Хотя бы даже не код, а словесное описание или блок-схему алгоритма...

Share this post


Link to post
Share on other sites
8 hours ago, des00 said:

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

При синтезе все равно будет как блокируещее,  так что не понимаю упорства.

Share this post


Link to post
Share on other sites
В 30.09.2019 в 14:48, pavlovconst сказал:

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

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

 

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

 

always @(posedge clk or negedge clk) ...

 

и попытаетесь скормить это синтезатору практически любой современной ПЛИС, то получите отлуп, т.к. такая конструкция предполагает реализацию в виде флопа, работающего по обоим фронтам, а таких в нынешних ПЛИС просто нет (вроде были в Spartan или Spartan2), в то время как симулятор это съест без проблем.

 

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

 

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

 

Блокирующие присваивания, кстати, очень даже применимы в тактируемых блоках, но только для вычисления значений переменных, используемых в правой части неблокирующих присваиваний - нередко это просто удобно и повышает читабельность, когда логика развесистая и нетривиальная. Для симулятора тут всё корректно: сперва вычисляются значения блокирующих (Active Region), причём итеративно (учитывая изменения переменных в других блоках в текущем дельта-цикле), затем они присваиваются через неблокирующие (NBA Region). Синтез тоже понимает эту логику и прекрасно разносит реализацию на комбинационную логику и флопы.

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