输入一个向量,如何从LSB或者MSB或者反过来找出第一个出现1的位置并生成独热码?这个问题碰到好多次了,今天总结一下。
这个电路有点类似于一个优先编码器(所以该电路就是固定优先级的仲裁器),例如对于一个4bit位宽的向量来说,其真值表如下
Input | Output |
---|---|
0001 | 0001 |
xx10 | 0010 |
x100 | 0100 |
1000 | 1000 |
上述真值表的Verilog电路实现如下
module OneHot(
input [3:0] din,
output [3:0] onehot
);
reg [3:0] onehot_w;
always@(*)begin
casex(din)
4'b0001:onehot_w = 4'b0001;
4'b001x:onehot_w = 4'b0010;
4'b01xx:onehot_w = 4'b0100;
4'b1000:onehot_w = 4'b1000;
endcase
end
assign onehot = onehot_w;
endmodule
第二种方法是一个比较巧妙的方法,并且进行参数化实现也比较方便。首先有这样一种求一个数的补码的方法:从LSB到MSB,找到第一个为1的位置,该位保持不变,之后一直到MSB所有的位都取反,即可得到该数的补码。稍加思索就可以发现,既然可以用这种方法找到补码,那换句话说补码就一定符合这个规则,那么补码就可以作为mask来找到第一个1出现的地方了:因为补码是从第一个1之后所有的位都取反,那么将原数与补码按位与,就得到了一个独热码,并且该独热码1出现的位置就是原数第一个1出现的位置。
module onehot(
parameter WIDTH = 8
)(
input [WIDTH-1:0] din,
output [WIDTH-1:0] onehot
);
wire [WIDTH-1:0] complement_w = ~(din-1);
assign onehot = din&complement_w;
endmodule
再添加一个参数用于调整寻找的方向,最终的设计如下
module onehot(
parameter WIDTH = 8,
parameter DIRECTION = 0
)(
input [WIDTH-1:0] din,
output [WIDTH-1:0] onehot
);
wire [WIDTH-1:0] din_w;
generate
if(DIRECTION==0)begin:gen_lsb_msb
assign din_w = din;
end
else begin:gen_msb_lsb
assign din_w = din[0:7];
end
endgenerate
wire [WIDTH-1:0] complement_w = ~(din_w-1);
assign onehot = din_w&complement_w;
endmodule
标签:din,第一个,complement,补码,寻找,WIDTH,onehot,assign
From: https://www.cnblogs.com/lzhj/p/18183845