Verilog で 64 ビットのバレル シフターを作成したい (今のところローテーション)。65パートのケースステートメントを書かずにそれを行う方法があるかどうか知りたいですか? 次のような簡単なコードを書く方法はありますか?
Y = {S[i - 1:0], S[63:i]};
ザイリンクスで上記のコードを試したところ、エラーが発生しました。i は定数ではありません。
主な質問: 巨大なケースステートメントなしでこれを行う方法はありますか?
Verilog で 64 ビットのバレル シフターを作成したい (今のところローテーション)。65パートのケースステートメントを書かずにそれを行う方法があるかどうか知りたいですか? 次のような簡単なコードを書く方法はありますか?
Y = {S[i - 1:0], S[63:i]};
ザイリンクスで上記のコードを試したところ、エラーが発生しました。i は定数ではありません。
主な質問: 巨大なケースステートメントなしでこれを行う方法はありますか?
わかりやすくするためにいくつかのルールを簡略化していますが、詳細は次のとおりです。
声明では
Y = {S[i - 1:0], S[63:i]};
2 つの信号の連結があり、それぞれに一定のパーツ選択があります。一定のパーツ選択は次の形式です
識別子 [ 定数式 : 定数式 ]
しかし、あなたのコードは最初の式に変数を使用しています。ご覧のとおり、これは許可されていませんが、大規模な case ステートメントを入力しないようにする方法があるという点では正しいです。代わりに使用できるのは、インデックス付きのパーツ選択です。これらは次の形式です
識別子 [式 +: 定数式]
識別子 [式 -: 定数式]
これらの構造は、左側の変数に関係なく、結果の信号の幅が一定であることを強制します。
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]
2 つのパーツ選択から 1 つの信号を構築しようとするのではなく、単純に入力信号を 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];
これを行うために私が見つけた最良の方法は、パターンを見つけることです。8 ビット信号を 1 位置 (8'b00001111 << 1) 左に回転させたい場合、結果は = 8'b00011110) になり、左に 9 位置 (8'b00001111 << 9) 回転させたい場合も結果は同じです。 = 8'b00011110、さらに 17 ポジションをローテーションすると、次のテーブルへの可能性が減少します。
したがって、見てみると、テーブル上のすべての数値のツリーの最初のビットは、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);
reg_out_tempはreg_in_1 の 2 倍になります。この場合、reg_out_tempは16 ビットで、reg_in_1 は 8 ビットになるため、データをシフトするときにキャリーされたビットを他のバイトに取得できるため、OR 式を使用してそれらを組み合わせることができます。
reg_out <= reg_out_temp[15:8] | reg_out_temp[7:0];
したがって、2 クロック サイクルで結果が得られます。16 ビット ローテーションの場合、マスクは8'b00011111 (8'h1F) になります。これは、シフトが 0 から 16 になり、一時レジスタが 32 ビットになるためです。