Verilog 驱动强度(drive strength)与电荷强度(charge strength)
定位 :本节内容面向具备 RTL 设计基础、正在向门级 / 器件级建模深入的工程师。重点在于 仿真精度与可读性 ,而 综合工具大多忽略强度信息 ------请务必把它们视为 建模-仿真利器,而非综合资源。
1 为什么要关心强度?
- 总线争用建模:多源驱动同一 net,需要判定最终值(如 I²C SDA、双向数据线)。
- 开启/关闭上拉电阻 :在 SPI、JTAG 等接口里,用
pullup
/pulldown
原语+弱驱动模拟外部电阻。 - 晶体管级行为 :在
nmos / pmos / tran
原语中通过电荷强度刻画"漏电量 / 保留电荷"。 - 验证 corner case :弱驱动 VS 强驱动冲突时产生
X
,可以及早发现设计缺陷。
2 驱动强度总览
Verilog 1995/2001 规定 8 档强度(按强→弱):
强度符号 | 典型含义 | 实际阻值(示意) |
---|---|---|
supply1 / supply0 |
接电源 / 地 | < 100 Ω |
strong1 / strong0 |
逻辑单元输出 | 100 Ω ~ 1 kΩ |
pull1 / pull0 |
上拉 / 下拉电阻 | 5 kΩ ~ 50 kΩ |
weak1 / weak0 |
漏极开路、内部保留 | > 50 kΩ |
highz1 / highz0 |
高阻 | ∞ |
解析原则
- 同一 net 若存在多源驱动,仿真器按照最强者优先。
- 同强度且值不同 → 结果
X
。 - 强度完全相同且值相同 → 取该值。
示例
verilog
wire (strong1, weak0) data_drv; // 强 1、弱 0 (pair 1:0)
wire (weak1, weak0) data_pull; // 弱 1、弱 0 (pair 1:0)
assign data_drv = dir ? 1'b1 : 1'bz; // 驱动器
pullup (pull1) (data_pull); // 上拉电阻
// 当 dir==1 时 strong1 胜出 -> net = 1
// 当 dir==0 时 high-Z + pull1 -> net 被上拉到 1
3 驱动强度的使用位置与语法
场景 | 语法关键字 | 例子 |
---|---|---|
网线/net 声明 | 强/弱对 (strength0, strength1) 或者单边 (strength) |
tri (weak1, weak0) sda; |
门级原语 | buf , and , or , ... 后接强度对 |
buf (pull1, strong0) u_buf (out, in); |
连续赋值 | assign (strength0, strength1) net = expr; |
assign (strong1, strong0) data = src; |
force/release | force (strong0, strong1) net = val; |
调试时修改总线 |
宏建模 | pullup , pulldown 自带强度 |
pullup p1 (line); |
注意 :综合工具(Vivado/Quartus/Libero)普遍 忽略括号中的强度声明,只取逻辑值。若想合成可用的三态,需要实例化厂商推荐的 IOBUF/ALT_IOBUF 原语。
4 电荷强度(charge strength)
仅在 开关级原语 (nmos
, pmos
, tranif*
, rtran*
等)出现,用于描述晶体管 存储电荷能力 。
可选 3 档 :small
< medium
< large
。
verilog
// 一个带电荷强度的 nmos 开关
nmos #(1, 4) // #(上升延迟, 下降延迟)
(medium) // 电荷强度
u_nmos (out, in, gate);
- 仿真器作用:控制关断瞬间节点保持电荷(衰减时间),多用于带模拟特性的混合信号模型。
- 综合层面 :完全无效------如需硬件实现请在 IP 级别用硬核 IO 资源或建模 RC 网络。
5 强度分辨算法深入(IEEE 1364-2005 节 6.1)
仿真器对每一对 0/1 驱动 建立一张 分辨表(简化):
| supply strong pull weak highz
------------------------------------------
supply | 0/1 0/1 0/1 0/1 0/1
strong | 0/1 0/1 0/1 0/1
pull | 0/1 0/1 0/1
weak | X X
highz | Z
- 斜线对角线表示同值互相清除;
X
区域表示同级别不同值冲突;Z
表示全高阻(无驱动或全部高阻)。
工程启示
- 若把 外部上拉 与 内部弱驱动 同时挂在总线上,要保证逻辑取值能被上层状态机覆盖,否则仿真会出现不必要的
X
。 - 强弱搭配 = "硬 件驱动 + 软件拉电阻" 是最常见组合。
6 实战演练:三态总线竞态检查
verilog
module tri_bus_demo;
reg cpu_en, dma_en;
reg cpu_data;
reg dma_data;
wire (strong1, strong0) data_drv_cpu;
wire (strong1, strong0) data_drv_dma;
wire (pull1, pull0) data_bus; // 总线
assign data_drv_cpu = cpu_en ? cpu_data : 1'bz;
assign data_drv_dma = dma_en ? dma_data : 1'bz;
assign data_bus = data_drv_cpu | data_drv_dma; // 多驱动汇聚
initial begin
cpu_en = 1; cpu_data = 0;
dma_en = 1; dma_data = 1; // 冲突!同强度不同值
#1 $display("bus=%b (期望 X)", data_bus);
#1 $stop;
end
endmodule
仿真波形 :
data_bus
出现X
,帮助验证仲裁逻辑。生产设计中应加入仲裁 / 总线空闲握手,或使用weaker
驱动降低冲突等级。
7 最佳实践 & 注意事项
建议 | 目的/说明 |
---|---|
仅在 testbench 或门级仿真 使用强度 | 避免综合与时序工具忽略后产生"误判差"。 |
Pullup/pulldown 建模 IO 上拉 | 建模外部电阻,方便 SPI/I²C 级联测试。 |
驱动与拉电阻强度差>=1 级 | 保证正常工作状态时逻辑值明确,空闲态由弱上拉决定。 |
避免在 assign 内使用不同强度组合拼接 |
难以阅读;推荐把强驱动 / 弱驱动分到不同 net。 |
电荷强度仅限 switch 原语 | 若要验证保持电荷现象,请同时设置 decay_time 等仿真器选项。 |
跨工具兼容 :highz1/highz0 并非所有工具都实现 |
某些仿真器只认 z ,建议上层用 tri , bufif 简化。 |
8 和静态时序(STA)的关系
驱动/电荷强度 不会进入 STA 图。
- STA 只看 逻辑路径、延迟模型、负载。
- 如果期望反映 DRC "过强/过弱" 现象,应在 PCB 级或硬核 IO Constraint(如
set_drive
) 中声明。
9 总结
- 驱动强度 = 多源决议工具 ,电荷强度 = 晶体管保持电荷工具 ;二者都是 仿真级建模属性。
- 在 FPGA 日常 RTL 中 ≈ "调试/验证辅料";硬件实现靠 IO Buffer、外部电阻、时钟架构来保证。
- 掌握它们能更真实地复现信号争用、总线空闲与泄放,为功能验证扫清隐患。