如何在Verilog中优化2D数组中的查找值

时间:2019-04-16 15:38:07

标签: function optimization system-verilog

我需要设置一个函数来确定2D数组(索引)中是否存在匹配项。 我目前的实现可行,但是由于if语句检查了数组的每个元素,因此正在创建大量的LUT。

function result_type index_search ( index_type index, logic[7:0] address );

     for ( int i=0; i < 8; i++ ) begin
         if ( index[i] == address ) begin
            result = i;
         end
     end

有没有一种方法可以更有效地检查比赛?

1 个答案:

答案 0 :(得分:0)

真的没什么可做的;至少对于手中的代码。由于您的代码针对的是硬件,因此要对其进行优化,请考虑硬件,而不是功能/ verilog代码。

对于没有任何已知数据模式的通用实现,您肯定需要(a)N W位相等性检查,以及(b)N:1 FPA(固定优先级仲裁器(又名优先级编码器,又名前导零检测器),假定输入N W位,它返回第一个匹配项。像这样:

enter image description here

没有太多优化要完成,但是下面是一些可能的通用优化:

  • 如果计时是一个问题,请如图所示进行管道铺设。
  • 考虑一种替代的FPA实现,该实现利用2的补码特性并可能导致更有效的LUT实现:assign fpa_out = fpa_in & ((~fpa_in)+1);(导致单次编码, not 加权二进制,就像您的代码一样)
  • 开始使用一键编码可能会派上用场,并减少您沿途的某些逻辑,但是直到我们看到更多代码后,我才能确定地说。

这是实现的样子:

logic[N-1:0] addr_eq_idx;
logic[N-1:0] result;
for (genvar i=0; i<N; i++) begin: g_eq_N
    // multiple matches may exist in this vector
    assign addr_eq_idx[i] = (address == index[i]) ? 1'b1 : 1'b0;

    // pipelined version:
    // always_ff @(posedge clk, negedge arstn)
    //     if (!arstn)
    //         addr_eq_idx[i] <= 1'b0;
    //     else
    //         addr_eq_idx[i] <= (address == index[i]) ? 1'b1 : 1'b0;
end

// result has a '1' at the position where the first match is found
assign result = addr_eq_idx & ((~addr_eq_idx) + 1);

最后,尝试考虑由于已知的运行时数据特征,您的设计是否可以简化。例如,假设您100%确定要查找的address可能存在于索引2D数组中的最多一个位置。如果是这种情况,那么您根本不需要FPA,因为第一个匹配项将是唯一的匹配项。在这种情况下,addr_eq_idx已经指向匹配索引,作为一个单向矢量。