找到序列第一个1
找序列第一个1需要一点技巧,首先给pre最高位赋0,然后pre的低7位等于pre的高7位和data的高7位相或,这里可能会产生一个疑问,明明pre的低7位都没赋值,都是x,怎么能直接取高7位来和data做或,那输出不都是x吗?
是这样的,pre[7]=0,在比较的时候,是1bit 1bit比较,因此组合逻辑会先计算pre[6]=pre[7]|data[7]。得到pre[6]的结果后,再计算pre[6]|data[6],以此类推。这个方法妙就妙在当算出1bit的pre为1时,后面的所有pre都为1,譬如data=8'b0010_1101
pre[7]=0
pre[6]=pre[7] | data[7]=0
pre[5]=pre[6] | data[6]=0
pre[4]=pre[5] | data[5]=1
pre[3]=pre[4] | data[4]=1
pre[2]=pre[1]=pre[0]=1
这样,再对pre进行按位取反的时候:
data=8'b0010_1101
~pre =8'b1110_0000
(~pre) & data = 8'b0010_0000
得到最高位的one_hot码,用这样的原理我们可以求得最高位的1,代码如下
代码
module find_first_1(
input [7:0] data ,
output [7:0] one_hot
);
wire [7:0] pre;
assign pre[7] = 0;
assign pre[6:0] = pre[7:1] | data[7:1];
assign one_hot = data & ~pre;
endmodule
testbench
module tb();
wire [7:0] one_hot;
reg [7:0] data;
initial begin
repeat(10) #10 data = $random%255;
#20 $finish();
end
initial begin
$fsdbDumpfile("find_one.fsdb");
$fsdbDumpvars(0);
end
find_first_1 u_find_first_1(
.data (data) ,
.one_hot (one_hot)
);
endmodule
波形
找到序列最后一个1
找序列最后一个1,就是用补码的性质,一个数和它的补码相与,得到最低位的1。
代码
module find_last_1(
input [7:0] data ,
output [7:0] one_hot
);
assign one_hot = data & ~(data-1);
endmodule
testbench
module tb();
wire [7:0] one_hot;
reg [7:0] data;
initial begin
repeat(10) #10 data = $random%255;
#20 $finish();
end
initial begin
$fsdbDumpfile("find_one.fsdb");
$fsdbDumpvars(0);
end
find_last_1 u_find_last_1(
.data (data) ,
.one_hot (one_hot)
);
endmodule