Я прочитал "Неблокирующие присвоения в Verilog Synthesis, убивающие стили кодирования!" пользователя Клиффорд Каммингс. Он говорит, что следующий код (стр. 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), похоже, дают один и тот же результат независимо от того, в какой форме присвоение используется.