Verilog баррель Shifter - PullRequest
       61

Verilog баррель Shifter

5 голосов
/ 25 сентября 2011

Я хочу создать 64-битный бочкообразный механизм в verilog (пока поверните вправо). Я хочу знать, есть ли способ сделать это без написания заявления о 65 частях дела? Есть ли способ написать простой код, такой как:

    Y = {S[i - 1:0], S[63:i]};

Я попробовал код выше в Xilinx и получил ошибку: я не является константой.

Основной вопрос: есть ли способ сделать это без огромного кейса?

Ответы [ 2 ]

10 голосов
/ 25 сентября 2011

Я упростил некоторые правила для ясности, но вот подробности.

В утверждении

Y = {S[i - 1:0], S[63:i]};

у вас есть объединение двух сигналов, каждый с константойВыбор части.Выбор константной части имеет вид

идентификатор [constant_expression: constant_expression]

, но ваш код использует переменную для первого выражения.Как вы видели, это недопустимо, но вы правы в том, что есть способы избежать ввода большого оператора case.Вместо этого вы можете использовать индексированную часть select.Они имеют вид

идентификатор [выражение +: константа_выражение]

идентификатор [выражение -: константа_экспрессия]

Этиконструкции гарантируют, что ширина результирующего сигнала будет постоянной, независимо от переменной на левой стороне.

wire [HIGH_BIT:LOW_BIT] signalAdd,signaSub;
signalAdd[some_expression +: some_range];
signalSub[some_expression -: some_range];
//Resolves to
signalAdd[some_expression + (some_range - 1) : some_expression];
signalSub[some_expression                    : some_expression - (some_range - 1)];

//The location of the high value depends on how the signal was declared:
wire [15: 0] a_vect;
wire [0 :15] b_vect;
a_vect[0 +: 8] // a_vect[7 : 0]
b_vect[0 +: 8] // b_vect[0 : 7]

Вместо того, чтобы пытаться построить один сигнал из двух выбранных частей, вы можете просто расширить входной сигналдо 128 бит, и используйте переменную часть, выбираемую из этого.

wire [63:0] data_in,data_out;
wire [127:0] data_in_double;
wire [5:0] select;

//Concatenate the input signal
assign data_in_double = {data_in,data_in};

//The same as signal[select + 63 : select]
assign data_out = data_in_double[select+63-:64];

Другой подход, который вы можете использовать, - генерировать циклы.Это более общий подход к репликации кода на основе переменной.Он гораздо менее эффективен, поскольку генерирует 4096 сигналов.

wire [63:0] data_in,data_out;
wire [127:0] data_in_double;
wire [5:0] select;
wire [63:0] array [0:63];
genver i;

//Concatenate the input signal
assign data_in_double = {data_in,data_in};
for(i=0;i<64;i=i+1)
  begin : generate_loop
  //Allowed since i is constant when the loop is unrolled
  assign array[i] = data_in_double[63+i:i];
  /*
  Unrolls to 
  assign array[0] = data_in_double[63:0];
  assign array[1] = data_in_double[64:1];
  assign array[2] = data_in_double[65:2];
  ...
  assign array[63] = data_in_double[127:64];
  */
  end

//Select the shifted value
assign data_out = array[select];
0 голосов
/ 21 февраля 2016

Лучший способ сделать это - найти шаблон. Если вы хотите повернуть влево 8-битный сигнал на 1 позицию (8'b00001111 << 1), то результат = 8'b00011110), а если вы хотите повернуть влево на 9 позиций (8'b00001111 << 9), результат будет таким же = 8'b00011110, а также вращение 17 позиций, это уменьшит ваши возможности до следующей таблицы: </p>

PATTERN_TABLE

так что если вы посмотрите, первые биты дерева всех чисел в таблице, эквивалентные позиции вращения 1 (1,9,17,25 ... 249), равны 001 (1)

первые биты дерева всех чисел в таблице, эквивалентные повороту на 6 позиций (6,14,22,30 ... 254), равны 110 (6)

, поэтому вы можете применить маску (8'b00000111) для определения правильного числа сдвига, обнуляя все остальные биты:

reg_out_temp <= reg_in_1 << (reg_in_2 & 8'h07); </strong>

reg_out_temp должен быть двойным от reg_in_1, в этом случае reg_out_temp должен быть 16-битным и reg_in_1 8-битным, так что вы можете получить перенесенные биты в другой байт при сдвиге данные, чтобы вы могли объединить их, используя выражение ИЛИ:

reg_out <= reg_out_temp [15: 8] | reg_out_temp [7: 0]; </strong>

так что за два такта вы получите результат. Для 16-битного вращения ваша маска должна быть 8'b00011111 (8'h1F), потому что ваши сдвиги идут от 0 до 16, а ваш временный регистр должен иметь 32 бита.

...