Inoutポート
CoddyのVerilogジャーニー「基礎」セクションの一部 — レッスン 32/90。
inout ポートは、信号の送信と受信の両方を行うことができる双方向ポートです。状況に応じて input または output として機能します。ほとんどのポートは input(データが内部へ流れる)または output(データが外部へ流れる)のいずれかです。inout ポートはその両方を行うことができ、状況に応じてデータを外部へドライブ(出力)したり、内部へ受信したりすることができます。
一方通行の道路ではなく、片側二車線の双方向の道路(対面通行)のようなものだと考えてみてください。
Inout ports は以下のような場合に使用されます:
- 共有バス — 複数のデバイスが同じ配線に接続されている場合
- メモリデータバス — データを読み出すことも書き込むこともできる場合
- 双方向通信 — I2C、SPI など
一度にbusを駆動(drive)するデバイスは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; // Drive bus when enabled, else Z
assign data_in = bus; // Always read the bus
endmodule- `enable = 1` のとき、モジュールはバスをドライブします(出力モード)
- `enable = 0` のとき、モジュールはバスを解放(ハイZ)します(入力モード)
Inout の重要なルール
| ルール | 理由 |
|---|---|
wire として宣言する必要がある | reg にすることはできない |
| 同時に読み込みと書き込みを行うことはできない | 競合 (X) が発生するため |
バスを解放するには Z を使用する | 他のデバイスがドライブできるようにするため |
| 同時にアクティブにできるドライバーは1つだけ | バスの競合を防ぐため |
Inout vs Input vs Output
| ポートの種類 | 方向 | Drive 可能か | Read 可能か |
|---|---|---|---|
input | 一方通行 (入力のみ) | いいえ | はい |
output | 一方通行 (出力のみ) | はい | いいえ |
inout | 双方向 (両方) | はい (有効な時) | はい (常に) |
よくある間違い
// WRONG: alwaysブロック内でinoutに代入できない
always @(posedge clk) begin
data_bus <= something; // Error! 条件付きでassignを使用してください
end
// CORRECT: enable条件付きでassignを使用する
assign data_bus = (enable) ? something : 8'bZ;チャレンジ
この双方向バッファを機能させるために、不足している inout ポートと assign 文を追加してください。
作業内容:
io_busという名前の 8-bitinoutポートを追加するsend_enableが 1 のときはio_busをsend_valueで駆動し、そうでないときはZにするassign文を追加するio_busをreceive_valueに読み込むassign文を追加する
自分で試してみよう
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のときにio_busをsend_valueで駆動し、それ以外はZにするassign文を追加する
// タスク3: io_busをreceive_valueに読み込むassign文を追加する
endmoduleこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。