Използване на блокиращи задания за извеждане на тригери във Verilog

Прочетох „Неблокиращи присвоявания в синтеза на Verilog, стилове на кодиране, които убиват!“ от Клифърд Къмингс. Той казва, че следният код (страница 12, опростена) е правилна реализация на джапанка, често използвана в учебниците, дори и да не е точно този вид, който всеки трябва да използва. документът спечели награда за най-добър документ, така че предполагам, че твърдението е вярно.

module ff (q, d, clk)
  output q;
  input d, clk;
  reg q;

  always @(posedge clk)
    q = d;
endmodule

Бих искал да знам защо това ще продължи да работи правилно, ако два или повече от тези джапанки са свързани последователно. Казвам

module two_ffs (q, d, clk)
  input d, clk;
  output q;

  wire tmp;

  ff firstff (tmp, d, clk);
  ff secondff (q, tmp, clk);
endmodule

Според мен е възможно стойността на tmp да се актуализира, преди да бъде използвана от secondff, което води до един тригер, а не два. Може ли някой да ми каже коя част от стандарта казва, че това не може да се случи? Много благодаря.

[не че някога бих си помислил да напиша код по този начин, просто искам да разбера поведението на блокиране/неблокиране дори в случаите, когато лошият стил на кодиране прави смисъла неочевиден]

Добавено по-късно:

Сега мисля, че хартията е малко вероятно да е правилна. Раздел 5 „Семантика на планиране“ на стандарта 1364-2201 Verilog обяснява какво се случва. По-конкретно, раздел 5.6.6 „Връзки на портове“ на страница 68 казва, че еднопосочните портове са точно като непрекъснати присвоявания. На свой ред непрекъснатото присвояване е просто винаги блок, чувствителен към всичко. Така че най-важното е, че двете инстанции на ff в моя пример по-долу са еквивалентни на модул с множество клаузи на always, за които всеки би се съгласил, че е счупен.

Добавено, след като Клайв Къмингс отговори на въпроса:

Благодарен съм на CC, че изтъкна, че твърденията по-горе, взети от раздел 5 на стандарта, се отнасят само до времето на събитията за актуализиране и не предполагат буквална еквивалентност между напр. някои непрекъснати задачи и винаги блокира. Въпреки това мисля, че те обясняват защо някои симулатори (напр. Icarus Verilog) ще произведат различни резултати от симулация с блокиращо и неблокиращо задание във "тригера". [В по-голям пример получих 2 очевидни ffs с блокиращо задание и правилните пет с неблокиращо.] Други симулатори (напр. Modelsim с опции по подразбиране или Cver) изглежда дават същия резултат, без значение коя форма на се използва присвояване.


person user1002059    schedule 25.06.2012    source източник
comment
Сигурни ли сте, че това е пример за правилно внедряване? Това ми изглежда като учебникарски пример за неправилен дизайн. Мисля, че вашето разбиране е правилно.   -  person Tim    schedule 26.06.2012
comment
Всъщност не виждам този първи раздел никъде в този документ. Мисля, че вероятно го четете погрешно или можете да посочите точно откъде сте взели този примерен код? Не го виждам на страница 12 (може да имам различна версия от вашата).   -  person Tim    schedule 26.06.2012
comment
Тим: съжалявам, че не предоставих връзка (добавена сега). Позовавам се на версия 1.3 на документа, докато вие намерихте версия 1.2. Извинявай отново. Той е в раздел 9 и в двата документа. Пример 13 показва модел на тригер, който се появява в повечето тестови книги на Verilog. Тогава надписът му е Simple flawed ..... но работи!.   -  person user1002059    schedule 26.06.2012
comment

Тъп въпрос: Вашият модел всъщност се казва DataModel?

  -  person Tim    schedule 26.06.2012
comment
Ако имате достъп до университетска библиотека, може да помислите за получаване на IEEE 1364.1 Стандарт за синтез на ниво на трансфер на регистър Verilog.   -  person    schedule 26.06.2012


Отговори (2)


Всичко -

Малко корекции и актуализации. Раздел 5.6.6 от стандарта Verilog от 2001 г. не казва, че „еднопосочните портове са точно като непрекъснатите присвоявания“, той казва „Портовете свързват процеси чрез неявни инструкции за непрекъснато присвояване“. Има разлика, която ще отбележа по-долу.

Второ, "непрекъснатото присвояване е просто винаги блок, чувствителен към всичко", не е вярно. Непрекъснати присвоявания Drive стойности към мрежи, които могат да бъдат управлявани от други източници с предварително дефинирани функции за разделителна способност, както е описано в Verilog Standard. Винаги блокира Change стойностите на променливите и последната процедурна промяна печели (без резолюция).

По отношение на моето описание на тригера с 1 винаги блок, моето описание в статията не е 100% точно (но обикновено е точно). 2-инстанцираният флип-флоп модел на теория има състояние на състезание, въпреки че рядко се среща. Състезанието рядко се наблюдава, защото когато правите винаги блокиращо присвояване на променлива, която е декларирана като изход, компилаторите на Verilog автоматично хвърлят „имплицитно изявление за непрекъснато присвояване“ (IEEE-1364-2001, раздел 5.6.6, 1-ви параграф) за преобразуване на процедурната променлива в net-Driving присвояване (никога не виждате това да се случва!) Това преобразуване обикновено е достатъчно, за да въведе еквивалента на неблокиращо закъснение при присвояване на порта , така че симулацията работи. Експериментирах в миналото с превключватели за оптимизиране на компилатора, които ефективно премахват модулните портове между тригерите и наблюдавах нежеланите условия на състезание, така че технически моето описание на добре 1-винаги тригер с присвояване на блокиране не е 100 % правилно; следователно все още трябва да използвате неблокиращите присвоявания, описани в документа.

Примерът за 2-винаги блокиращо присвояване в същия модул има определено условие за състезание. Както е написано, вероятно ще работи, защото повечето компилатори изпълняват кода отгоре надолу, но ако обърнете реда на винаги блоковете, вероятно ще видите състезание.

Поздрави - Cliff Cummings - Verilog & SystemVerilog Guru

person Cliff Cummings    schedule 27.06.2012

Четене на Версия 1.3 на документа, Раздел 9 Пример 13. Текстът под него обяснява че е ОК, ако модулът съдържа само един винаги блок. Сегашното ми разбиране е, че това не е проблем между отделни модули. Позволете на вашия пример да работи. Въпреки това, ако даден модул съдържа множество винаги блокове, тогава редът на изпълнение е недефиниран и ще доведе до условията на състезание, за които се говори в раздел 2 на хартия.

Примерът по-долу е почти същият като примера с 2 флопа във въпроса, с изключение на това, че е в 1 модул и следователно има недефиниран ред на изпълнение, това вероятно няма да работи.

module ff (q, d, clk)
  output reg q;
  input d, clk;
  reg d_delay ;

  always @(posedge clk)
    d_delay = d;

  always @(posedge clk)
    q = d_delay;

endmodule
person Morgan    schedule 26.06.2012
comment
Мислех също, че планирането между модулите е някак специално. Но стандартът казва, че не е така. Вижте новодобавения коментар в горната част. Много благодаря за отговора. - person user1002059; 27.06.2012