FPGA基础 -- Verilog 驱动强度(drive strength)与电荷强度(charge strength)
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
。 - 强度完全相同且值相同 → 取该值。
示例
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
。
// 一个带电荷强度的 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 实战演练:三态总线竞态检查
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 begincpu_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、外部电阻、时钟架构来保证。
- 掌握它们能更真实地复现信号争用、总线空闲与泄放,为功能验证扫清隐患。