Verilog 中可以递归实例化吗?

Mat*_*lor 5 recursion verilog system-verilog

有些问题会导致递归解决方案。Verilog 中可以递归实例化吗?模块是否可以实例化自身?

Mat*_*lor 5

有些问题会导致递归解决方案。求一组数的最小值就是这样一个工作:基本上,一组数的最小值是前半部分的最小值和后半部分的最小值中的最小值。

取一组数字。将这个集合分成两半。求每一半的最小值。整组的最小值是每半组最小值中的较小者。你如何找到每一半的最小值?好吧,每一半都是一组数字,因此对于每一半,请回到本段的开头......

这是递归的。最终,你得到一组单一的数字。该集合的最小值显然就是该数字,因此问题变得微不足道,这就是递归解决问题的要点。那么,我们如何使用递归实例化在硬件中做到这一点呢?

我们需要一个具有 N 个输入的可参数化模块。在模块内部,如果 N 大于 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
Run Code Online (Sandbox Code Playgroud)

有两个参数:N 是输入的数量,W 是每个输入的宽度。不幸的是,有一个复杂的情况:Verilog 不允许阵列端口。相反,我们必须使用宽度为 N*W 的单个向量输入。您可以在代码中看到这一点。这使代码变得复杂,因为必须进行计算来索引该输入向量的位。

因此,我们代码的核心是生成块。在其中,我们测试参数 N 以查看我们正在处理多少个输入。如果我们处理一个输入,那么工作很简单:最小值恰好等于该一个输入。否则,我们要处理多个输入,因此将一半输入发送到 MinN 模块的一个实例,并将其余输入发送到另一个实例。在生成块之外,我们通过比较每个子块的输出来确定总体最小值。

当然,这在 SystemVerilog 中是可能的,因为 Verilog 是 SystemVerilog 的子集。但在 SystemVerilog 中实际上会更容易,因为您可以使用阵列端口。

这是可以合成的。