Необязательные параметры функции, которых нет в списке чувствительности при вызове из assign

Я думаю, что понял, почему это происходит, но я хотел бы подтвердить это и посмотреть, есть ли лучшее решение.

Рассмотрим следующий модуль, в котором есть функция, в которой значение по умолчанию для одного из параметров привязано к некоторому регистру внутри модуля:

module m;
  reg a, b;
  wire out;
  function f1 (input x, input y = b);
    f1 = x & y;
  endfunction :f1

  // ...
  assign out = f1(a);
endmodule

Проблема, которую я вижу (которую было нелегко отследить), заключается в том, что в этом случае в списке конфиденциальности задания есть только a. Таким образом, если b изменится, а затем изменится a, out будет правильно обновлен. Однако если изменяется a, а затем изменяется b, так как b нет в списке чувствительности для назначения out, out не будет обновляться и будет по-прежнему установлено старое значение.

Есть ли предпочтительный способ добавить b в список чувствительности, чтобы out обновлялся при его изменении?

Я вижу несколько возможных вариантов:

  1. Просто явно добавьте второй аргумент: f1(a, b)
  2. Используйте непрерывный блок присваивания always_comb out = f1(a) или always @(*) out=f1(a)
  3. Используйте явный список конфиденциальности always @(a, b) out = f1(a)

Лично я думаю, что вариант 1 является лучшим (хотя он будет повторять необязательные параметры в каждом месте, где он вызывается), но мне любопытно, есть ли другие объяснения или лучшее решение.


person techdude    schedule 17.01.2020    source источник


Ответы (1)


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

Вариант 3 больше не вариант, как вы обнаружили, это кошмар для отладки.

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

always_comb begin
          phase_one_stuff;
          phase_two_stuff;
          if (mode==A)
               mode_A_stuff;
          else
               mode_B_stuff;
          phase_three_stuff;
       end

Не используйте @(*) в SystemVerilog. always_comb заменяет его и имеет то преимущество, что имеет дело с начальными значениями времени 0, к которым @(*) может быть нечувствительным.

person dave_59    schedule 17.01.2020
comment
Да, 3 — это не то, что я использую лично, потому что это позволяет очень легко рассинхронизировать вещи. @(*) включен только для полноты, но всегда_comb был бы предпочтительным вариантом из двух. - person techdude; 18.01.2020
comment
В этом приложении функция является настоящей постоянной функцией, поэтому 2, вероятно, лучший вариант, поскольку он не требует дублирования функций. - person techdude; 18.01.2020