在 Verilog 中,wire 和 wor 都属于线网类型(net type) ,用于表示硬件中的连线。它们最大的区别在于:如何处理多个驱动源同时驱动同一根线的情况。
一、核心区别一览
| 特性 | wire | wor |
|---|---|---|
| 全称 | wire(普通连线) | wired-OR(线或) |
| 多驱动时的行为 | 多驱动通常导致冲突(X 态) | 多驱动按"或"逻辑合并 |
| 典型用途 | 普通信号连接 | 多源信号合并、open-drain 模拟 |
| 可综合性 | 完全可综合 | 部分综合工具支持有限,常用于仿真建模 |
| 默认值 | 高阻态 Z | 高阻态 Z |
| 属于的类别 | 普通 net | 解决冲突的 net(resolved net) |
二、wire 的行为详解
wire 是 Verilog 中最常用的线网类型,只能有一个驱动源 。如果有多个驱动源同时驱动 wire,结果是不确定的(X 态)。
示例 1:wire 单驱动(正常情况)
module wire_demo (
input wire a,
input wire b,
output wire y
);
// wire 由 assign 单驱动,正常工作
assign y = a & b;
endmodule
仿真行为: y 正确反映 a & b 的结果。
示例 2:wire 多驱动(冲突导致 X)
module wire_conflict (
input wire a,
input wire b,
output wire y
);
// ⚠️ 两个 assign 同时驱动 y,发生冲突
assign y = a;
assign y = b;
endmodule
仿真行为:
- 当
a=1, b=0时,y = X(冲突) - 当
a=0, b=1时,y = X(冲突) - 当
a=b时,y才有确定值
这就是 wire 的限制:不能合并多个驱动源。
三、wor 的行为详解
wor 允许多个驱动源同时驱动一根线,多驱动的结果按**"或"逻辑**合并。这种特性来自早期硬件的"线或"总线(用 open-collector 输出 + 上拉电阻实现)。
wor 的真值表
| 驱动 1 | 驱动 2 | wor 结果 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
| 0 | Z | 0 |
| 1 | Z | 1 |
| Z | Z | Z |
| X | 任意 | X |
示例 3:wor 多驱动(按 OR 合并)
module wor_demo (
input wire a,
input wire b,
input wire c,
output wor y // 注意:用 wor 而非 wire
);
// 三个驱动源同时驱动 y,按 OR 合并
assign y = a;
assign y = b;
assign y = c;
// 等价于 assign y = a | b | c;
endmodule
仿真行为:
a=0, b=0, c=0→y = 0a=1, b=0, c=0→y = 1a=0, b=1, c=1→y = 1- 任何一个为 1,
y都是 1
示例 4:wor 模拟多模块共享中断总线
这是 wor 最经典的应用场景------多个外设共享一根中断线。
module interrupt_bus (
input wire irq_uart, // UART 中断
input wire irq_timer, // 定时器中断
input wire irq_gpio, // GPIO 中断
output wor irq_to_cpu // 合并后的中断信号到 CPU
);
// 多个中断源通过 wor 合并:任意一个为 1,CPU 就收到中断
assign irq_to_cpu = irq_uart;
assign irq_to_cpu = irq_timer;
assign irq_to_cpu = irq_gpio;
endmodule
硬件含义: 模拟早期处理器中"中断线或"的设计,任何一个外设拉高中断线,CPU 都能感知到。
示例 5:wor 在 testbench 中的对比测试
`timescale 1ns/1ps
module tb_wire_vs_wor;
reg a, b;
wire y_wire;
wor y_wor;
// 同样的多驱动场景,分别用 wire 和 wor
assign y_wire = a;
assign y_wire = b;
assign y_wor = a;
assign y_wor = b;
initial begin
$monitor("Time=%0t a=%b b=%b | y_wire=%b y_wor=%b",
$time, a, b, y_wire, y_wor);
a = 0; b = 0; #10; // y_wire=0 y_wor=0
a = 1; b = 0; #10; // y_wire=X y_wor=1
a = 0; b = 1; #10; // y_wire=X y_wor=1
a = 1; b = 1; #10; // y_wire=1 y_wor=1
$finish;
end
endmodule
仿真输出(关键差异):
Time=0 a=0 b=0 | y_wire=0 y_wor=0
Time=10 a=1 b=0 | y_wire=x y_wor=1 ← wire 冲突变 X,wor 正确为 1
Time=20 a=0 b=1 | y_wire=x y_wor=1 ← wire 冲突变 X,wor 正确为 1
Time=30 a=1 b=1 | y_wire=1 y_wor=1
四、wor 的"近亲":其他 resolved net 类型
Verilog 还有几个类似的"解决冲突"线网类型,理解它们有助于全面把握:
| 类型 | 多驱动合并逻辑 | 典型应用 |
|---|---|---|
| wor / trior | OR(按位或) | 中断总线、状态合并 |
| wand / triand | AND(按位与) | open-drain I2C 总线、共享请求线 |
| tri | 同 wire,但强调三态 | 双向总线 |
| tri0 | 无驱动时下拉为 0 | 模拟带下拉电阻的信号 |
| tri1 | 无驱动时上拉为 1 | 模拟带上拉电阻的信号 |
| trireg | 保持上次驱动的值 | 模拟电容性总线 |
对比示例:wand 模拟 I2C 总线
module i2c_bus_demo (
input wire master_sda, // 主机 SDA
input wire slave1_sda, // 从机 1 SDA
input wire slave2_sda, // 从机 2 SDA
output wand sda // I2C 数据线(线与)
);
// I2C 总线是 open-drain,任何一个拉低就为低
assign sda = master_sda;
assign sda = slave1_sda;
assign sda = slave2_sda;
endmodule
真值表: 任何一个为 0,结果就是 0;全部为 1,结果才是 1。这就是 I2C "线与"的硬件本质。
五、实际使用建议
✅ 使用 wire 的场景(99% 的情况)
- 普通信号连接、模块端口
- 任何只有一个驱动源的信号
- RTL 设计中默认就用 wire
⚠️ 使用 wor 的场景(特殊情况)
- 行为级建模、抽象建模、TLM 模型
- 仿真早期阶段模拟多源合并
- 教学或特殊验证场景
❌ 不推荐使用 wor 的场景
-
可综合 RTL 设计中尽量避免 wor :
- 大多数综合工具对
wor/wand支持有限或会发出警告 - 现代设计推荐显式写出 OR 逻辑,更清晰、更可移植
- 大多数综合工具对
-
推荐写法:
// ❌ 不推荐:用 wor 隐式合并
output wor irq;
assign irq = irq_a;
assign irq = irq_b;
assign irq = irq_c;// ✅ 推荐:显式 OR 逻辑
output wire irq;
assign irq = irq_a | irq_b | irq_c;
六、一句话总结
| 类型 | 一句话概括 |
|---|---|
| wire | 普通连线,只能单驱动,多驱动会冲突变 X |
| wor | "线或"连线,多个驱动按 OR 合并,仿真建模用,RTL 设计建议显式写 OR 替代 |
口诀: wire 单驱动,wor 多驱动按或合并,RTL 设计尽量用 wire + 显式逻辑。