找到序列最高位的1和最高位的0并输出位置

 前言:

        该题为睿思芯科笔试题,笔试时长20分钟。

题目描述

        接口如下:

module first_1_and_0#(
    parameter WIDTH = 8
)(
    input   [WIDTH-1:0]         data_in ,
    input                       target  ,
    output                      exist   ,
    output  [$clog2(WIDTH):0]   pos
);

         target可以等于1,也可以等于0。当target等于1时,检测data_in最高位的1,并输出其位置,位置计数从0开始。举例:当target=1时,序列4'b0101,存在1,所以输出exist = 1,检测1的位置pos=1。


题目解析

        找到序列第一个1的位置,可以参考笔者本篇博客:不用循环和分治,仅用“按位”操作,找到序列第一个1和最后一个1

        找到第一个0的位置,可以利用同样的思想。首先给pre最高位赋1,然后pre的低7位等于pre的高7位和data的高7位相与,这里可能会产生一个疑问,明明pre的低7位都没赋值,都是x,怎么能直接取高7位来和data做或,那输出不都是x吗?

        是这样的,pre[7]=1,在比较的时候,是1bit 1bit比较,因此组合逻辑会先计算pre[6]=pre[7] & data[7]。得到pre[6]的结果后,再计算pre[6] & data[6],以此类推。这个方法妙就妙在当算出1bit的pre为0时,后面的所有pre都为0,譬如data=8'b1110_1101

pre[7]=1

pre[6]=pre[7] & data[7]=1

pre[5]=pre[6] & data[6]=1

pre[4]=pre[5] & data[5]=1

pre[3]=pre[4] & data[4]=0

pre[2]=pre[1]=pre[0]=0

这样,再对pre进行按位取反的时候:

data=8'b1110_1101

pre  =8'b1111_0000

这时候,我们再利用性质:一个数和它自身的补码相与,结果为最低位的1。

找到pre的最低位的1:pre & ~(pre - 1)=8'b0001_0000,这时候one_hot码1的位置就是data中最高位0的位置了。

利用(WIDTH-$clog2(one_hot_0)-1)就可以输出0的position了,代码如下:


代码

module first_1_and_0#(
    parameter WIDTH = 8
)(
    input   [WIDTH-1:0]         data_in ,
    input                       target  ,
    output                      exist   ,
    output  [$clog2(WIDTH):0]   pos
);

// signal defination
wire [WIDTH-1:0] find_1_pre,find_0_pre;
wire [WIDTH-1:0] one_hot_1,one_hot_0;
wire             exist_1,exist_0;
wire [$clog2(WIDTH):0] pos_0,pos_1; 

//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

testbench

module tb#(
    parameter WIDTH = 8
)();

reg target;
reg [WIDTH-1:0] data_in;
wire exist;
wire [$clog2(WIDTH):0] pos;

initial begin 
    target  =  1'b0;
    data_in =  8'd0;
#10
    target  =  1'b1;
#10
    data_in =  8'b11111111;
    target  =  1'b1;
#10
    target  =  1'b0;
    data_in =  8'b10110110;
    target  =  1'b0;
#10
    target  =  1'b1;
#10
    data_in =  8'b00110101;
    target  =  1'b0;
#10
    target  =  1'b1;
#10
    $finish();
end

first_1_and_0 u_first(
    .target (target     ),
    .data_in(data_in    ),
    .exist  (exist      ),
    .pos    (pos        )
);

initial begin
    $fsdbDumpfile("first_1_and_0.fsdb");
    $fsdbDumpvars(0);
end
endmodule 

波形图

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 是的。二进制是一种基于数字0和1的数值系统,它是由一串数字0和1组成的数字序列。每个0或1称为一个“”(bit),一组8个组成一个“字节”(byte)。在计算机中,所有内部数据都以二进制形式存储和处理。 ### 回答2: 是的,二进制是一种由数字0和1组成的数字序列。它是一种计数系统,与我们通常使用的十进制系统不同。在二进制系统中,每数字只能是0或1,没有其他数字。这是因为二进制系统是基于2的幂次方的计数系统。 在二进制系统中,每个数字位置代表了其对应的权重。最右边的数字的权重是2的0次方,然后是2的1次方,2的2次方,以此类推。通过在每个位置上使用0或1,我们可以表示任意整数。例如,二进制数1101表示的十进制数是13,其中最高(左边第一)的权重是2的3次方,而第二是2的2次方,第三是2的1次方,最后一是2的0次方。 二进制在计算机科学和电子学中被广泛使用,因为它对于数字的表示和处理非常方便。计算机中的所有数据都是以二进制的形式存储和处理的。所以,对于计算机科学的学习和理解,了解和掌握二进制是非常重要的。 ### 回答3: 是的,二进制是由数字0和1组成的数字序列。在二进制系统中,每一上的数值只能是0或1,这是因为二进制采用了基数为2的计数系统。在二进制中,数字位置对应着不同的权重,每个位置上的数值乘以相应的权重后,再将它们相加就可以得到最终的十进制数。由于计算机直接使用二进制进行运算和存储,因此理解和掌握二进制对计算机科学和计算机编程非常重要。通过简单的组合和排列,二进制可以表示任意的十进制数字、字符、图像等信息,因此广泛应用于计算机领域。总之,二进制是一种由0和1组成的数字序列,在计算机中具有重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃葱的酸菜鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值