Дополнительные параметры функции отсутствуют в списке чувствительности при вызове из назначения - PullRequest
1 голос
/ 17 января 2020

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

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

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

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

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

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

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

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

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

1 Ответ

2 голосов
/ 18 января 2020

Вариант 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, к которым @(*) может не быть чувствительным.

...