如何快速定位一个二进制数字中第一个1的位置
用分级找吧,比如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
谢谢啦
这个确实比分级查找的要快一点,特别是位数很多的时候;如果全部改为组合逻辑,估计会更快。