Verilog中,如果只有一个高电平,则将电线置为高。

5
如果我有一个由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?它也必须是合成化的。

6个回答

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

问候-Cliff Cummings-Verilog & SystemVerilog专家


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);

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);

变量i是整数还是寄存器? - e19293001
在这个例子中,i 将是一个整数。由于循环将在编译时展开,因此仍然可以合成。 - Morgan

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中编写此内容。


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

-2

从逻辑的角度思考:你想要什么? 假设你有两根电线:你想知道其中一根是高电平还是低电平……它不是与门,也不是或门……等等,它是异或门(exclusive or,即一个或另一个但不是两个都有)。

所以你想要的是: assign exactlyOneActive = data[0] ^ data[1] ^ data[2] ^ ...

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


但是 1 ^ 1 ^ 1 = 0 ^ 1 = 1。我认为这告诉我所有的是,我有一个奇数高位。 - Dax Fohl
哎呀,你说得对。你需要的是一个一位加法器(这样你就可以知道是否有进位,即两个位都是0或1)。 - dave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接