目录
前言
个人学习简单总结,方便自己后续查询和复习
一、找到序列的第一个1
1、思路
1)最高位的pre[N-1]赋值0,让pre[N-2:0] = pre[N-1:1] | data[N-1:1],可以得到当找到第一个1位置后面的pre都为1。
2)然后通过data & ~pre可以得到第一个1位置的独热码
3)最后,利用(N-$clog2(one_hot)-1)就可以输出第一个1的位置
2、代码
module find_first_1 (
input [N-1:0] data,
output [N-1:0] one_hot
);
wire [N-1:0] pre;
assign pre[N-1] = 0;
assign pre[N-2:0] = data[N-1:1] | pre[N-1:1];
assign one_hot = data & (~pre);
endmodule
二、找到序列的最后一个1
1、思路
方式一:一个数和它的补码相与;方式二:参考第一个1的思路
2、代码
方式一代码如下:
module find_last_1 (
input [N-1:0] data,
output [N-1:0] one_hot
);
assign one_hot = data & (~(data-1));
endmodule
方式二代码如下:
module find_last_1 (
input [N-1:0] data,
output [N-1:0] one_hot
);
wire [N-1:0] pre;
assign pre[0] = 0;
assign pre[N-1:1] = pre[N-2:0] | data[N-2:0];
assign one_hot = data & (~pre);
endmodule
三、找到序列的第一个0
1、思路
方式1:参考找序列的第一个的思路:高位的pre[N-1]赋值1,让pre[N-2:0] = pre[N-1:1] & data[N-1:1],可以得到当找到第一个0位置后面的pre都为0。然后找pre的最低位的1就是要找data最高位0的位置,用数和数的补码相与进行运算求出。
方式2:将输入的data全部按位取反,按照找序列的第一个1去找
2、代码
方式1的代码如下:
module find_first_0 (
input [N-1:0] data,
output [N-1:0] one_hot
);
wire [N-1:0] pre;
assign pre[N-1] = 1;
assign pre[N-2:0] = pre[N-1:1] & data[N-1:1];
assign one_hot = pre & (~pre);
endmodule
四、其他思路
如对折查找,for循环等实现
对折查找实现代码如下:
module find_first_one(
input [7:0] data,
output [2:0] result
);
wire [3:0] data_4;
wire [1:0] data_2;
assign result[2] = | data[7:4];
assign data_4 = result[2] ? data[7:4] : data[3:0];
assign result[1] = |data_4[3:2];
assign data_2 = result[1] ? data_4[3:2] : data_4[1:0];
assign result[0] = data_2[1];
endmodule
五、相关题目
如下接口,target可以为1,也可以为0。当target等于1是,检测data_in最高位的1,并输出其位置,位置计数从0开始。
module first_1_and_0 #(
parameter WIDTH = 8
)(
input [WIDTH-1:0] data_in,
input target,
output exist,
output [$clog2(WIDTH):0] pos
);
//signals
wire [WIDTH-1:0] find_1_pre;
wire [WIDTH-1:0] one_hot_1;
wire exist_1;
wire [$clog2(WIDTH):0] pos_1;
wire [WIDTH-1:0] find_0_pre;
wire [WIDTH-1:0] one_hot_0;
wire exist_0;
wire [$clog2(WIDTH):0] pos_0;
//find first 1
assign find_1_pre[WIDTH-1] = 0;
assign find_1_pre[WIDTH-2:0] = find_1_pre[WIDTH-1:1] | data_in[WIDTH-1:1];
assign one_hot_1 = data_in & (~find_1_pre);
assign exist_1 = |data_in;
assign pos_1 = exist_1 ? (WIDTH -$clog2(one_hot_1)-1) :0;
//find first 0
assign find_0_pre[WIDTH-1] = 1;
assign find_0_pre[WIDTH-2:0] = find_0_pre[WIDTH-1:1] & data_in[WIDTH-1:1];
assign one_hot_0 = find_0_pre & (~find_0_pre-1);
assign exist_0 = !(&data_in);
assign pos_0 = exist_0 ? (WIDTH -$clog2(one_hot_0)-1) :0;
//output
assign exist = target ? exist_1 : exist_0;
assign pos = target ? pos_1 : pos_0;
endmodule