Inoutポート
CoddyのVerilogジャーニー「基礎」セクションの一部 — レッスン 32/90。
inout ポートは、信号の送信と受信の両方を行うことができる双方向ポートです。これは、時によって入力または出力として機能します。
ほとんどのポートは、input(データが入力される)またはoutput(データが出力される)のいずれかです。inoutポートはその両方が可能です。状況に応じて、データを出力したり、入力を受け取ったりすることができます。
一方通行の道路ではなく、双方向の道路のように考えてください。
Inoutポートは以下のような場合に使用されます:
- 共有バス — 同じ配線に接続された複数のデバイス
- メモリデータバス — データの読み取りまたは書き込みが可能
- 双方向通信 — I2C、SPIなど
一度にバスを駆動できるデバイスは1つだけです。他のデバイスはハイインピーダンス状態 (Z) である必要があります。
Inoutポートの宣言
inout [7:0] data_bus; // 8ビット双方向バス
inout ready; // 1ビット双方向信号Inoutの仕組み
inoutポートは、それが入力をとして機能するか、出力をとして機能するかを決定するための制御信号を必要とします。
module bidir (
inout [7:0] bus,
input [7:0] data_out,
input enable,
output [7:0] data_in
);
assign bus = (enable) ? data_out : 8'bZ; // 有効な時はバスを駆動し、それ以外はZ(ハイインピーダンス)
assign data_in = bus; // 常にバスを読み取る
endmoduleenable = 1のとき、モジュールはバスを駆動します(出力モード)enable = 0のとき、モジュールはバスを解放します(入力モード、high-Z)
Inoutに関する重要なルール
| ルール | 理由 |
|---|---|
wireとして宣言する必要があります | regにすることはできません |
| 同時に読み書きすることはできません | 競合(X)が発生します |
バスを解放するためにZを使用します | 他のデバイスが駆動できるようになります |
| 一度に一つのドライバのみ | バスの衝突を防ぎます |
Inout vs Input vs Output
| ポートタイプ | 方向 | ドライブ可能 | 読み取り可能 |
|---|---|---|---|
input | 単方向 (入力のみ) | いいえ | はい |
output | 単方向 (出力のみ) | はい | いいえ |
inout | 双方向 (両方) | はい (有効時) | はい (常に) |
よくある間違い
// 誤り: alwaysブロック内でinoutに代入することはできません
always @(posedge clk) begin
data_bus <= something; // エラー!条件付きのassignを使用してください
end// 正解: イネーブル条件付きで assign を使用する
assign data_bus = (enable) ? something : 8'bZ;チャレンジ
不足している inout ポートと assign 文を追加して、この双方向バッファを動作させてください。
作業内容:
io_busという名前の 8ビットinoutポートを追加します。send_enableが 1 のときはio_busをsend_valueで駆動し、それ以外の場合はZとするassign文を追加します。io_busをreceive_valueに読み込むassign文を追加します。
チートシート
inout は、信号の送信(ドライブ)と受信の両方が可能な双方向ポートです。一度にバスをドライブできるデバイスは1つだけで、他のデバイスは高インピーダンス (Z) を出力しなければなりません。
module bidir (
inout [7:0] bus,
input [7:0] data_out,
input enable,
output [7:0] data_in
);
assign bus = (enable) ? data_out : 8'bZ; // 有効な時にドライブし、それ以外は解放する
assign data_in = bus; // 常にバスを読み取る
endmodule主なルール:
wire型である必要があります(regは不可)- 三項演算子を用いた
assign文を使用します。alwaysブロック内での代入は決して行わないでください - バスの衝突を避けるため、ドライブしていない時は
Zで解放します
自分で試してみよう
module bidir_buffer (
// タスク 1: ここに io_bus という名前の 8 ビット inout ポートを追加します
input [7:0] send_value,
input send_enable,
output [7:0] receive_value
);
// タスク 2: send_enable が 1 のときは send_value で io_bus を駆動し、それ以外の場合は Z とする assign 文を追加します
// タスク 3: io_bus を receive_value に読み込む assign 文を追加します
endmoduleこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。