Провод высокий, если ровно один высокий в Verilog

Если у меня есть массив из 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? Он также должен быть синтезируемым.


person Dax Fohl    schedule 20.06.2012    source источник


Ответы (6)


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

С уважением - Клифф Каммингс - Verilog & SystemVerilog Guru

person Cliff Cummings    schedule 27.06.2012

Это должен быть довольно эффективный дизайн.

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);
person Morgan    schedule 22.06.2012

Я думаю, что-то вроде этого должно работать. Цикл 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);
person Tim    schedule 20.06.2012
comment
является ли переменная i целым числом или регистром? - person e19293001; 22.06.2012
comment
i в этом примере будет целым числом. Это все еще можно синтезировать, поскольку цикл будет развернут во время компиляции. - person Morgan; 05.11.2012

Все остальные решения требуют 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)

где вы проверяете совокупный xor, xor каждой пары, xor каждой группы из 4, xor каждой группы из 8 (не показано) и т. д., дает вам правильный ответ в воротах O (N log (N)). . (Вы можете проверить логику на генераторе таблиц истинности ). Не уверен, как написать это в краткой форме на Verilog.

person Dax Fohl    schedule 29.06.2012

Вот решение ворот 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
person Dax Fohl    schedule 30.06.2012

Подумайте с точки зрения логики: чего вы хотите? Скажем, у вас было два провода: и вы хотели знать, один высокий или нет ... это не и, это не или ... подождите, это xor (исключающее или ... один или другой, но не оба) .

так что вы хотите: назначить точно OneActive = data[0] ^ data[1] ^ data[2] ^ ...

возможно, допустимо следующее: data ^ 1b'0 (xor все биты с одним нулевым битом)

person dave    schedule 29.06.2012
comment
Но 1 ^ 1 ^ 1 = 0 ^ 1 = 1. Думаю, все, что мне говорит, это то, что у меня нечетное количество старших битов. - person Dax Fohl; 29.06.2012
comment
Упс. Ты прав. Что вам нужно, так это однобитовый сумматор (чтобы вы могли сказать, есть перенос или нет, т.е. оба бита были равны 0 или 1). - person dave; 30.06.2012