Возможна ли рекурсивная реализация в Verilog? - PullRequest
4 голосов
/ 22 марта 2019

Некоторые проблемы приводят к рекурсивному решению. Возможна ли рекурсивная реализация в Verilog? Возможно ли для модуля создать экземпляр себя?

1 Ответ

3 голосов
/ 22 марта 2019

Некоторые проблемы приводят к рекурсивному решению. Найти минимум набора чисел - это как раз такая работа: в основном минимум набора чисел - это минимум минимума первой половины и минимум второй половины.

Взять набор чисел. Разделите этот набор пополам. Найдите минимум каждой половины. Минимум всего набора является наименьшим из минимумов каждой половины. Как вы находите минимум каждой половины? Ну, каждая половина - это набор чисел, поэтому для каждой половины вернитесь к началу этого абзаца ...

Это рекурсивно. В конце концов, вы получаете набор из одного номера. Минимум этого набора, очевидно, равен этому числу, поэтому проблема становится тривиальной, что является точкой рекурсивного решения чего-либо. Итак, как мы можем сделать это на аппаратном уровне, используя рекурсивную реализацию?

Нам нужен параметризуемый модуль с N входами. Внутри модуля, если N больше 2, мы создаем 2 копии модуля и направляем половину входов на один и половину входов на другой. Выход модуля в этом случае является меньшим из выходов этих 2 подмодулей. Если N равно 1, мы просто подключаем вход прямо к выходу. Вот и все.

Чтобы сделать это в Verilog, нам нужно будет использовать параметры и, учитывая, что мы можем что-то создавать или не создавать, генерировать операторы.

Итак, вот реализация Verilog этого алгоритма:

module MinN #(parameter N = 8, W=16) (input [(N*W)-1:0] I, output [W-1:0] Min);
  wire [W-1:0] Min1, Min2;
  generate
    if (N == 1)
      begin : Neq1
        assign Min1 = I;
        assign Min2 = I;
      end
    else
      begin : Ngt1
        MinN #(.N(N-(N/2)), .W(W)) M1 (.I(    I[(N*W)-1:((N/2)*W)]), .Min(Min1));
        MinN #(.N(N/2),     .W(W)) M2 (.I(I[((N/2)*W)-1:        0]), .Min(Min2));
      end
  endgenerate
  assign Min = (Min1 < Min2) ? Min1 : Min2;
endmodule

Существует два параметра: N - количество входов и W - ширина каждого. К сожалению, есть сложность: Verilog не разрешает порты массива. Вместо этого мы должны использовать один векторный ввод шириной N * W. Вы можете увидеть это в коде. Это усложняет код, поскольку затем необходимо выполнить вычисления для индексации битов этого входного вектора.

Итак, ядром нашего кода является блок генерации. Внутри этого мы проверяем параметр N, чтобы увидеть, сколько входов мы имеем дело. Если мы имеем дело с одним входом, то задача проста: минимальное значение просто равно этому одному входу. В противном случае мы имеем дело с более чем одним входом и отправляем половину входов одному экземпляру модуля MinN, а остальные - другому. Вне блока генерации мы определяем общий минимум, сравнивая выходные данные каждого субблока.

Конечно, это возможно в SystemVerilog, потому что Verilog является подмножеством SystemVerilog. Но на самом деле это будет проще в SystemVerilog, потому что вам разрешены порты массива.

И это синтезируемо.

...