verilog-5| 找到序列第一个1、最后一个1、第一个0

目录

前言

一、找到序列的第一个1

1、思路

2、代码

二、找到序列的最后一个1

1、思路

2、代码

三、找到序列的第一个0

1、思路

2、代码

四、其他思路

五、相关题目


前言

个人学习简单总结,方便自己后续查询和复习


一、找到序列的第一个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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值