Loading

如何判断输入是独热码Verilog

问题展现

前几天面试手撕了一个很有意思的代码,如何判断一组输入数据是否是独热码。

我的解答:

 1 module cal1num_simple(
 2     input         wire            clk,
 3     input         wire             rst,
 4     // input           wire                 valid,
 5     input         wire     [31:0]    din,
 6     output        wire               flag
 7     );
 8 
 9 reg     [5:0] ones;
10 
11 integer i;
12 
13 always@(*)begin
14     ones = 0;
15     for(i=0;i<32;i=i+1)begin
16         ones = ones + din[i];
17     end
18 end
19 
20 assign flag = (ones==1);
21 
22 endmodule
View Code

占用的资源:

这里考虑到对PPA进行优化,我一开始是判断输入是有多少个1然后输出,但是如果位宽比较大就会消耗较多资源,现记录一下另一种方法看看资源情况。

这里简单在ISE上综合看看资源情况,改进后的代码如下:

这里的技巧是先判断输入中是否具有奇数个1,因此用到奇偶校验,再利用独热码独特的性质:其经过一个运算后从1开始那一位及以上的位都为1,再利用独热码取反与其或操作得到一个全1的序列。

如果不是独热码那么经过这个运算后从1开始那位及以上会出现0,原序列取反与其或操作就得到的不是全1了,利用按位与就可以判断了。

 1 module cal1num_simple(
 2     input         wire            clk,
 3     input         wire             rst,
 4     input         wire     [31:0]    din,
 5     output        wire               flag
 6     );
 7 
 8 wire      is_odd;
 9 wire [31:0]     din_q;
10 
11 assign is_odd = (^din)==1;
12 
13 assign din_q[0] = din[0];
14 
15 generate
16     genvar i;
17     for(i=1;i<32;i=i+1)begin
18         assign din_q[i] = din_q[i-1] ^ din[i];
19     end
20 endgenerate
21 
22 assign flag = is_odd ? (&((~din) | din_q)==1 ? 1 : 0) : 0;
23 
24 endmodule
View Code

可以看出两者在输入数据位宽为32位时竟然一样,那么增加位宽为64

第一个资源利用:

第二种资源利用:

LUT用77下降到21,可以看出节约了大量资源!

要点分析

 

posted @ 2022-07-25 16:35  月光小猪(已长膘)  阅读(984)  评论(0)    收藏  举报