有些问题会导致递归解决方案。 Verilog中可以递归实例化吗?模块是否可以实例化自己?
最佳答案
有些问题会导致递归解决方案。求一组数的最小值就是这样的工作:基本上,一组数的最小值是前半部分的最小值和后半部分的最小值中的最小值。
取一组数字。将该组分成两半。找出每一半的最小值。整个集合的最小值是每一半的最小值中的较小者。你如何找到每一半的最小值?好吧,每一半都是一组数字,所以对于每一半,回到本段的开头......
它是递归的。最终,您会得到一组一个数字。该集合的最小值显然是那个数字,所以问题变得微不足道,这就是递归解决问题的关键。那么,我们如何在硬件中使用递归实例化来做到这一点呢?
我们需要一个具有 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
有两个参数:N 是输入的数量,W 是每个的宽度。不幸的是,有一个复杂的问题:Verilog 不允许阵列端口。相反,我们必须使用宽度为 N*W 的单个向量输入。您可以在代码中看到这一点。这使代码复杂化,因为必须进行计算以索引该输入向量的位。
所以,我们代码的核心是生成 block 。在其中,我们测试参数 N 以查看我们正在处理多少个输入。如果我们处理一个输入,那么工作很简单:最小值正好等于那个输入。否则,我们将处理多个输入,因此将一半的输入发送到 MinN 模块的一个实例,其余的发送到另一个实例。在生成 block 之外,我们通过比较每个子 block 的输出来确定总体最小值。
当然,这在 SystemVerilog 中是可能的,因为 Verilog 是 SystemVerilog 的一个子集。但在 SystemVerilog 中实际上会更容易,因为您可以使用阵列端口。
这是可以合成的。
关于recursion - Verilog中可以递归实例化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55296169/