双向端口
本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 32 课,共 90 课。
inout 端口是双向端口,可以发送和接收信号。它可以在不同时间充当输入端或输出端。大多数端口要么是 input(数据流入),要么是 output(数据流出)。inout 端口两者都能做到。它可以向外驱动数据,也可以接收流入的数据,具体取决于情况。
把它想成一条双向街道,而不是单行道。
输入输出端口用于:
- 共享总线:多个设备连接到同一组线路
- 内存数据总线:可以读取或写入数据
- 双向通信:I2C、SPI 等
总线上一次只能有一个设备驱动总线。其他设备必须处于高阻态(Z)。
声明 Inout 端口
inout [7:0] data_bus; // 8 位双向总线
inout ready; // 单比特双向信号输入和输出的工作原理
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时,模块释放总线(输入模式,高阻态)
Inout 的重要规则
| 规则 | 原因 |
|---|---|
必须声明为 wire | 不能是 reg |
| 不能让多个设备同时驱动总线 | 相互冲突的驱动会产生 X |
使用 Z 释放总线 | 允许其他设备驱动总线 |
| 同一时间只能有一个驱动器 | 防止总线争用 |
双向端口与输入端口、输出端口的区别
| 端口类型 | 方向 | 能否驱动 | 能否读取 |
|---|---|---|---|
input | 单向(仅输入) | 否 | 是 |
output | 单向(仅输出) | 是 | 是(它驱动的值) |
inout | 双向(输入和输出) | 是(启用时) | 是(始终可以) |
常见错误
// 错误:不能在 always 块内给 inout 赋值
always @(posedge clk) begin
data_bus <= something; // 错误!请用 assign 配合条件赋值
end
// 正确:用 assign 配合 enable 条件赋值
assign data_bus = (enable) ? something : 8'bZ;挑战
添加缺失的 inout 端口和 assign 语句,让这个双向缓冲器正常工作。
要做什么:
- 添加一个名为
io_bus的 8 位inout端口 - 添加一条
assign语句:当send_enable为 1 时,用send_value驱动io_bus;否则使用Z - 添加一条
assign语句,将io_bus读入receive_value
亲手试试
module bidir_buffer (
// 任务 1:在这里添加一个名为 io_bus 的 8 位双向端口。
input [7:0] send_value,
input send_enable,
output [7:0] receive_value
);
// 任务 2:添加一条 assign 语句,当 send_enable 为 1 时,用 send_value 驱动 io_bus,否则将其设为 Z。
// 任务 3:添加一条 assign 语句,将 io_bus 的值读入 receive_value。
endmodule这节课包含一个小测验。开始学习即可作答,并记录你的进度。
基础知识中的所有课
自己练习: Verilog 在线编译器