微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 如何快速定位一个二进制数字中第一个1的位置

如何快速定位一个二进制数字中第一个1的位置

时间:10-02 整理:3721RD 点击:
比如二进制数00000000...1000...00,如何快速找到其中的“1”的位置?因为我要找的二进制数位数比较多,超过了100位,所以用一般的case语句编写起来比较麻烦,有没有更简便的方法?

用分级找吧,比如128位,先判断前64位等不等于0,不等于0,那就拆分这前64位;等于0,1就在后64位中,拆分;将64拆成2个32,再判断,。这样一级级定位,可以吧?

分段最好了,每8位为一段,并行查找



    这样会不会占用很多资源?



    要定位8位的一段就需要3位输出,128位那就需要48位输出了,感觉还是不太行得通

你是想要一个时钟周期就出结果,还是怎么的?



   最好是一个时钟周期



   那你肯定得面积换时间了,得多用资源


我先试一下吧,非常感谢

向左移位,判断最高位是否为1


如果是个200位的数据,那就需要200个时钟周期,这时间太长了



    用组合逻辑做,只有判断移位和+1操作在FPGA内可一很快的完成。

用if/else语句了,从第0开始扫描



    组合逻辑怎么实现?可以写一段简短的代码吗



   怎么会是48位呢?只有7位啊,8位检测产生的3位总是处于低3位的。高4位是由16个8位段的有无结果按照从右到左扫描产生的。

仔细想了一下:
如果需要在一个时钟周期得到结果的话,直接用并行的if语句分别对每个bit直接判断
,相当于优先级编码。
  if bit[1] == 1 begin
       cnt <= 1;
   end
  if bit[2] == 1 begin
       cnt <= 2;
   end
  if bit[3] == 1 begin
       cnt <= 3;
   end
  
        .
        .
        .
  if bit[127] == 1 begin
       cnt <= 127;
  end

多谢多谢



   这地址也太宽了吧

以前做过一个类似的模块,小编看下有没有帮助;
用了3拍查找出来的
http://www.eetop.cn/blog/505866/viewspace-564193.html


太宽了,一百多位如果都用作ROM地址,不可行。如果分段的话,按照小编一个周期出结果的要求,时序上也满足不了。
想了半天我认为小编只是嫌case语句写起来麻烦,使用并行if的优先级编码方式应该
是他想要的结果。


这样应该可以吧
always@(*)  //data2 64 bits
begin
  if(data1[127:64] == 0)
  begin
    pos[6] = 1'b0;
    data2  = data1[63:0];
  end
  else
  begin
    pos[6] = 1'b1;
    data2  = data1[127:64];
  end
  
end
always@(*)  //data3 32 bits
begin
  if(data2[63:32] == 0)
  begin
    pos[5] = 1'b0;
    data3  = data2[31:0];
  end
  else
  begin
    pos[5] = 1'b1;
    data3  = data2[63:32];
  end
  
end
always@(*)  //data4 16 bits
begin
  if(data3[31:16] == 0)
  begin
    pos[4] = 1'b0;
    data4  = data3[15:0];
  end
  else
  begin
    pos[4] = 1'b1;
    data4  = data3[31:16];
  end
  
end
always@(*)  //data5 8 bits
begin
  if(data4[15:8] == 0)
  begin
    pos[3] = 1'b0;
    data5  = data4[7:0];
  end
  else
  begin
    pos[3] = 1'b1;
    data5  = data4[15:8];
  end
  
end
always@(*)  //data6 4 bits
begin
  if(data5[7:4] == 0)
  begin
    pos[2] = 1'b0;
    data6  = data5[3:0];
  end
  else
  begin
    pos[2] = 1'b1;
    data6  = data5[7:4];
  end
  
end
always@(*)  //data7 2 bits
begin
  if(data6[3:2] == 0)
  begin
    pos[1] = 1'b0;
    data7  = data6[1:0];
  end
  else
  begin
    pos[1] = 1'b1;
    data7  = data6[3:2];
  end
  
end
always@(*)
begin
    if(data7[1] == 0)
      pos[0] = 1'b0;
  else
      pos[1] = 1'b1;
  
end


个人的看法:
这样和使用并行if的优先级编码方式,理论上是一个道理。这种方法是你代替编译工具,完成了优先级编码。
而使用并行if的方法是把这个工作交给编译软件去做,性能和资源的使用方面我认为是一样的。
不过你这样写,比写128个if要简洁一些。


我写了一个16位的可以试试,我仿真过了,可以的
always @ (posedge clk)begin
    data_vld_d1 <= data_vld;
end
always @ (*)begin
if (data_vld) begin
     data = data_in;
     cnt = 'b0;
end
else begin
     if (data_vld_d1) begin
         if ((~data[15]) && (cnt <= 4'd15)) begin
             cnt = cnt + 1;
             data = data << 1;
          end
          else begin
          end
//       else begin
//       end
       end
end
end
always @ (posedge clk or negedge resetn)begin
if (data_vld_d1) begin
     firstbit <= 4'd15 - cnt;
     end
end



    我谢了一个16位的,仿真过了,你可以试试
always @ (posedge clk)begin
    data_vld_d1 <= data_vld;
end
always @ (*)begin
if (data_vld) begin
     data = data_in;
     cnt = 'b0;
end
else begin
     if (data_vld_d1) begin
         if ((~data[15]) && (cnt <= 4'd15)) begin
             cnt = cnt + 1;
             data = data << 1;
          end
          else begin
          end
//       else begin
//       end
       end
end
end
always @ (posedge clk or negedge resetn)begin
if (data_vld_d1) begin
     firstbit <= 4'd15 - cnt;
     end
end



    谢谢啦



    这个确实比分级查找的要快一点,特别是位数很多的时候;如果全部改为组合逻辑,估计会更快。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top