で、もっと柔軟に入れ替えできないもんかな、と以前ちょっと考えてみた回路を書いてみた。
案外あっさりと動いた。
module bitswap_recursive ( A, Y, P ); parameter P_WIDTH = 64; parameter P_DEPTH = 3; parameter P_SPLIT_WIDTH_L = P_WIDTH/2 ; parameter P_SPLIT_WIDTH_H = P_WIDTH - (P_WIDTH/2); parameter P_SPLIT_DEPTH = P_DEPTH-1; input [P_WIDTH-1:0] A; output [P_WIDTH-1:0] Y; input [P_DEPTH-1:0] P; wire [P_SPLIT_WIDTH_L-1:0] lower; wire [P_SPLIT_WIDTH_H-1:0] higher; generate begin : gene if ( P_DEPTH == 1 ) begin assign lower = A[ P_SPLIT_WIDTH_L-1:0]; assign higher = A[P_WIDTH-1:P_SPLIT_WIDTH_L ]; end else begin bitswap_recursive #( .P_WIDTH( P_SPLIT_WIDTH_L ), .P_DEPTH( P_DEPTH-1 ) ) ins_lower ( .A( A[P_SPLIT_WIDTH_L-1:0] ), .Y( lower ), .P( P[P_SPLIT_DEPTH -1:0] ) ); bitswap_recursive #( .P_WIDTH( P_SPLIT_WIDTH_H ), .P_DEPTH( P_DEPTH-1 ) ) ins_higher ( .A( A[P_WIDTH-1:P_SPLIT_WIDTH_L] ), .Y( higher ), .P( P[P_SPLIT_DEPTH-1:0] ) ); end end // endgenerate // assign Y=(P[P_DEPTH-1])? { lower, higher } : { higher, lower }; endmodule //
使い方はこんな感じ。
- P_WIDTHでデータのビット幅、P_DEPTHで深さを指定。P_WIDTHを(2^P_DEPTH)分割した単位で入れ替えるので、P_WIDTH=64, P_DEPTH=3なら byte単位の入れ替えということになる。
- 入れ替えのパタンは 入力ポートPで指定し、MSBが 1であれば 入力ポートAの上半分と下半分を入れ替える。これを再帰的にP_DEPTH=1まで繰り返すだけ。
- 一応記述では P_WIDTHが2^nに乗っていない場合もカバーしたつもりだけど、まったく未確認、というかたぶん使い道ないのでP_WIDTHは2^nに合わせた方が吉。
- P_DEPTHは1~log2(P_WIDTH)の範囲で動くはず。これ以上大きくするとビット未満のスワップという意味分からない状態になってしまうはずなので設定禁止。
シミュレータでコンパイル通って、思った通りに動いていることまでは確認したが、これ、論理合成できるの??という。
やりたいことが何となくできちゃったので、ここから先の検証とかやらずこのまま寝かせちゃう。