在 Verilog 中以 log2 时间查找数组的最大值?

Finding the maximum value of an array in log2 time in Verilog?

我设计了一个 'sorter' 来寻找其输入的最大值,即 16 个 31 位字。在模拟中,它可以工作,但我不确定它是否可以在硬件中工作(因为它似乎没有按计划在 FPGA 上工作)。有人可以让我知道这是否有效吗?我试图节省资源,这就是为什么我试图重用同一个寄存器。谢谢...

module para_sort(clk, ready, array_in, out_max)
input clk, ready;
input [16*31-1:0] array_in;
output reg [30:0] out_max;
reg [30:0] temp_reg [0:15]
integer i, j;

always @ (posedge clk)
begin
   if(ready)
   begin
      for(j=0; j<16; j=j+1)
      begin
      temp_reg[j] <= array_in[31*(j+1)-1 -: 31];
      end
      i<=0;
      done<=0;
   end
   else
   begin
      if(i<4)
      begin
      for(j=0; j<16; j=j+1)
         if(temp_reg[j+1] > temp_reg[j]
         temp_reg[((j+2)>>1)-1] <= temp_reg[j+1]
         else
         temp_reg[((j+2)>>1)-1] <= temp_reg[j]

      i<=i+1;
      end
   end

   if(i == 4)
   begin
      out_max <= temp_reg[0];
      done <=1;
      i <= i + 1;
   end
   if(i == 5)
      done <=0;
end
endmodule

抱歉,代码太长了。如果您对代码有任何疑问,请告诉我。

在回答问题之前,我假设您对代码语法和语义没有任何问题,并且该模块是设计的一部分,因此您对 I/O 引脚数没有问题,似乎是这样。

首先,在此发布的代码中使用的算法不正确。也许你的意思不同,但这个是不正确的。以下代码对我有用:

//The same code as you posted, but slight changes are made
//Maybe you have tried compiling this code and missed some points while posting
module para_sort(clk, ready, array_in, out_max, done);
input clk, ready;
input [16*31-1:0] array_in;
output reg [30:0] out_max;
output reg done;
reg [30:0] temp_reg [0:16];
integer i, j;

always @ (posedge clk)
begin
   if(ready)
   begin
      for(j=0; j<16; j=j+1)
      begin
      temp_reg[j] <= array_in[31*(j+1)-1 -: 31];
      end
      i<=0;
      done<=0;
   end
   else
   begin
      if(i<4)
      begin
      for(j=0; j<16; j=j+2)
        begin
         if(temp_reg[j+1] > temp_reg[j])
           temp_reg[((j+2)>>1)-1] <= temp_reg[j+1];
         else
           temp_reg[((j+2)>>1)-1] <= temp_reg[j];

        end // end of the for loop
        i<=i+1;
      end
   end

   if(i == 4)
   begin
      out_max <= temp_reg[0];
      done <=1;
      i <= i + 1;
   end
   if(i == 5)
      done <=0;
end
endmodule

如果上面的代码没有解决问题,那么:

可能是时序问题Quartus Prime软件中有网表查看器工具(Vivado也一样)。当您检查生成的电路时,您可以看到包含许多组合块和反馈的路径(主要由第二个 for 循环引起)。如果第二个 for 循环没有足够的时间在单个时钟内完成执行,您将失去同步并且结果将不可预测。

所以,

  • 先试试上面的代码
  • 如果代码没有解决你的问题,那就试试FSM(用caseif - else - if语句)即使代码变长或看起来更丑(不友好) ,它对FPGA硬件更友好。