在 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(用
case
和if - else - if
语句)即使代码变长或看起来更丑(不友好) ,它对FPGA硬件更友好。
我设计了一个 '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(用
case
和if - else - if
语句)即使代码变长或看起来更丑(不友好) ,它对FPGA硬件更友好。