Verilog Nビット双方向シフトレジスタ:設計と実装完全ガイド
シフトレジスタの基本
シフトレジスタは、フリップフロップをカスケード接続し、共通クロックで動作させることで、ビット列を1クロックごとに1ビットずつシフトさせる回路です。データ入力dから入力されたビットが順次伝播し、出力outから並列または直列に取り出せます。
設計:パラメータ化双方向シフトレジスタ
ビット幅MSB、方向制御dir(0=右シフト、1=左シフト)、イネーブルen、アクティブローリセットrstnを備えた汎用設計です。
module shift_reg #(
parameter MSB = 8
)(
input d, // シリアルデータ入力
input clk, // クロック
input en, // イネーブル
input dir, // 方向: 0=右シフト, 1=左シフト
input rstn, // アクティブローリセット
output reg [MSB-1:0] out // 並列出力
);
always @(posedge clk) begin
if (!rstn)
out <= 0;
else if (en) begin
case (dir)
1'b0: out <= {out[MSB-2:0], d}; // 右シフト: LSB側にdを入力、MSB側から排出
1'b1: out <= {d, out[MSB-1:1]}; // 左シフト: MSB側にdを入力、LSB側から排出
endcase
end
// en=0ならout保持(暗黙の保持)
end
endmodule
シフト方向のイメージ
右シフト(dir=0):out = [b7,b6,b5,b4,b3,b2,b1,b0] → [b6,b5,b4,b3,b2,b1,b0,d]
左シフト(dir=1):out = [b7,b6,b5,b4,b3,b2,b1,b0] → [d,b7,b6,b5,b4,b3,b2,b1]
ハードウェア回路図
テストベンチ
16ビット幅で、リセット解除後、右シフト→方向切替→左シフト→保持のシナリオを実行します。
module tb_sr;
parameter MSB = 16;
reg data;
reg clk;
reg en;
reg dir;
reg rstn;
wire [MSB-1:0] out;
shift_reg #(MSB) sr0 (
.d(data), .clk(clk), .en(en), .dir(dir), .rstn(rstn), .out(out)
);
always #10 clk = ~clk; // 20ns周期 = 50MHz
initial begin
clk <= 0; en <= 0; dir <= 0; rstn <= 0; data <= 1'b1;
end
initial begin
// 1. リセット
rstn <= 0; #20 rstn <= 1; en <= 1;
// 2. 右シフトで7クロック、dataを交互に切替
repeat (7) @(posedge clk) data <= ~data;
// 3. 左シフトに切替、さらに7クロック
#10 dir <= 1;
repeat (7) @(posedge clk) data <= ~data;
// 4. 入力固定で7クロックシフト継続
repeat (7) @(posedge clk);
$finish;
end
initial $monitor("rstn=%0b data=%b en=%0b dir=%0b out=%b", rstn, data, en, dir, out);
endmodule
シミュレーション結果抜粋
ncsim> run rstn=0 data=1 en=0 dir=0 out=xxxxxxxxxxxxxxxx rstn=0 data=1 en=0 dir=0 out=0000000000000000 // リセットでクリア rstn=1 data=1 en=1 dir=0 out=0000000000000000 // イネーブル開始 rstn=1 data=0 en=1 dir=0 out=0000000000000001 // 右シフト: d=0入力 rstn=1 data=1 en=1 dir=0 out=0000000000000010 rstn=1 data=0 en=1 dir=0 out=0000000000000101 rstn=1 data=1 en=1 dir=0 out=0000000000001010 rstn=1 data=0 en=1 dir=0 out=0000000000010101 rstn=1 data=1 en=1 dir=0 out=0000000000101010 rstn=1 data=0 en=1 dir=0 out=0000000001010101 // 7クロック後 rstn=1 data=0 en=1 dir=1 out=0000000001010101 // dir=1に切替 rstn=1 data=1 en=1 dir=1 out=0000000000101010 // 左シフト開始 rstn=1 data=0 en=1 dir=1 out=1000000000010101 rstn=1 data=1 en=1 dir=1 out=0100000000001010 ... rstn=1 data=1 en=1 dir=1 out=1111110101010000 Simulation complete via $finish(1) at time 430 NS + 0
波形観測ポイント
- 緑ハイライト:
en=1でシフト動作中 - 黄ハイライト:
dir切替(右→左) - 青ハイライト:
data固定でシフトのみ継続
実用的な拡張機能
| 機能 | 実装ヒント |
|---|---|
| パラレルロード | input load, [MSB-1:0] din追加、if (load) out <= din優先 |
| シリアル出力 | output sout、右シフトならout[0]、左ならout[MSB-1] |
| 循環シフト | dir=0: {out[0], out[MSB-1:1]}、dir=1: {out[MSB-2:0], out[MSB-1]} |
| 可変シフト量 | input [$clog2(MSB):0] shamt、バレルシフタ構造で実装 |