Menu
CoddyTech

双向端口

本课属于 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;
challenge icon

挑战

添加缺失的 inout 端口和 assign 语句,让这个双向缓冲器正常工作。

要做什么:

  1. 添加一个名为 io_bus 的 8 位 inout 端口
  2. 添加一条 assign 语句:当 send_enable 为 1 时,用 send_value 驱动 io_bus;否则使用 Z
  3. 添加一条 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
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

基础知识中的所有课

自己练习: Verilog 在线编译器