4

如果我有 9 根线的阵列,如果 9 根线中恰好有一根是高的,是否有一种简单的方法可以制作一根高的新线?我知道我能做到

wire[8:0] data;
wire exactlyOneActive;
assign exactlyOneActive = (data[0] & !data[1] & !data[2] ...) | 
                          (!data[0] & data[1] & !data[2] ...) |
                          (!data[0] & !data[1] & data[2] ...) |
                          ...etc

但是,糟糕,对吧?特别是因为九根线在某个时候可能是 25 根。任何更好的方法来做到这一点,也许使用generate?它也必须是可合成的。

4

6 回答 6

6
assign zeroOrOnehot     = ~|(data & (data-1));
assign atLeastOneBitSet = |data;
assign exactlyOneActive = zeroOrOnehot & atLeastOneBitSet;  

问候 - Cliff Cummings - Verilog 和 SystemVerilog 大师

于 2012-06-27T22:20:02.800 回答
4

这应该是一个非常有效的设计。

wire[8:0] data;
wire exactly_one_active;

//Total is log2_ceiling of data bits wide
// Remove binary weighting
wire  [3:0] total = data[8] + data[7] ... + data[0]; 

assign exactly_one_active = (total == 4'b1);
于 2012-06-22T13:23:38.170 回答
2

我认为这样的事情应该有效。只要 For 循环有一个恒定的循环计数器,它就可以合成,如下所示:

#define N 8

wire [N:0] data;

reg [N:0] uniqueActive;

always @(data) begin
   for (i=0 ; i < N; i = i+1 ) begin
      uniqueActive[i] = (data == 1<<i);
   end
end

assign exactlyOneActive = (uniqueActive != 0);
于 2012-06-20T00:56:31.973 回答
1

所有其他解决方案都需要 O(N^2) 门。请注意以下模式

(a#b#c#d#e#f#g#h) & (a&b # c&d # e&f # g&h) & (a&b&c&d # e&f&g&h)

在哪里测试聚合异或,每对的异或,每组 4 的异或,每组 8 的异或(未显示)等,在 O(N log(N)) 门中给出正确答案. (您可以在真值表生成器上验证逻辑)。不知道如何在 Verilog 中以简洁的方式编写它。

于 2012-06-29T19:36:50.560 回答
1

这是一个 O(N) 门解决方案

wire[8:0] wires;
wire isOneHot;
wire[8:-1] moreThanOne;
wire[8:-1] atLeastOne;

genvar i;
generate
    for (i=0; i<9; i=i+1) begin :b1
        assign atLeastOne[i] = atLeastOne[i-1] | wires[i];
        assign moreThanOne[i] = moreThanOne[i-1] | atLeastOne[i-1] & wires[i];
    end
    assign isOneHot = atLeastOne[8] & !moreThanOne[8];
endgenerate
于 2012-06-30T16:03:43.760 回答
-2

从逻辑的角度思考:你想要什么?假设您有两条线:并且您想知道是高还是不高...不是与,不是或...等等,它是异或(独占或...一个或另一个,但不是两者) .

所以你想要的是:分配完全OneActive = data[0] ^ data[1] ^ data[2] ^ ...

也许以下是合法的: data ^ 1b'0 (异或所有位与一个零位)

于 2012-06-29T05:32:35.440 回答