group-telegram.com/enginegger/92
Last Update:
Возвращаясь
к напечатанному. Как известно, Verilator не поддерживает неблокирующие присваивания в initial
, и даже превращает их в блокирующие, если проигнорировать предупреждение. Это наследие cycle-accurate природы симулятора и в современных реалиях, когда он стал по сути event-driven, может приводить к гонкам.
Есть несколько способов обхода этой особенности, таких как присвоение сигналам значения на обратном фронте клока, использование единичной задержки, и даже вот такого финта, предложенного автором Верилятора.
К сожалению, первые два не сильно пригодны, когда у вас уже написаны таски, которые не хочется переписывать. А последний, авторский, теперь и вовсе не работает. Раньше работал, но потом Верилятор стал лучше соответствовать стандартам
В общем, в результате небольшого эксперимента, опытным путём был выработан следующий способ, одинаково работающий на всех имеющихся в моём распоряжении симуляторах:
logic start_trigger;
initial begin
start_trigger = 1'b0;
#0;
start_trigger = 1'b1;
end
always @(start_trigger) begin
// Здесь делаем то, что обычно делаем в initial
end
Такой квази-initial работает так же, как обычный, за исключением того, что выполняется после всех настоящих
initial
. При этом, внутри него можно использовать неблокирующие присваивания и задержки.Надеюсь, что Верилятор больше не поломают, и способ будет годен до тех пор, пока не появится настоящая поддержка неблокирующих присваиваний в
initial
.P.S.: Это третий вариант (после авторского). Второй недавно сломали