5.3 三态门与多驱动总线


文档摘要

5.3 三态门与多驱动总线 本节摘要:三态门让「多个驱动源共享一根线」成为可能,net 类的裁决规则决定共享线上最终是什么值。芯片间总线与双向引脚的建模离不开它,但芯片内部应该用多路选择器替代三态——这一节讲清两者的边界。 现场重建的最后一站,处理物理世界里最「不像程序」的连接方式:一根线上挂多个驱动源。软件世界里「多个写者共享一个变量」是并发问题,硬件世界里它是接线问题——三态门就是语言给出的接线答案。 三态门家族与裁决规则 三态门四个兄弟,按「使能时是否反相、使能电平高低」命名:bufif1(使能高时正向传输)、bufif0(使能低时传输)、notif1 与 notif0(使能时反相传输)。

5.3 三态门与多驱动总线

本节摘要:三态门让「多个驱动源共享一根线」成为可能,net 类的裁决规则决定共享线上最终是什么值。芯片间总线与双向引脚的建模离不开它,但芯片内部应该用多路选择器替代三态——这一节讲清两者的边界。

现场重建的最后一站,处理物理世界里最「不像程序」的连接方式:一根线上挂多个驱动源。软件世界里「多个写者共享一个变量」是并发问题,硬件世界里它是接线问题——三态门就是语言给出的接线答案。

三态门家族与裁决规则

三态门四个兄弟,按「使能时是否反相、使能电平高低」命名:bufif1(使能高时正向传输)、bufif0(使能低时传输)、notif1 与 notif0(使能时反相传输)。使能无效时输出高阻 z,等于从线上「把手拿开」:

module tri_bus_demo( input wire sel_a, sel_b, input wire [7:0] data_a, data_b, output wire [7:0] bus ); // 两个驱动源共享 bus:同一时刻至多一个使能 bufif1 drv_a(bus, data_a, sel_a); bufif1 drv_b(bus, data_b, sel_b); // pullup 给总线一个弱默认值:无人驱动时读到 1 而不是 z // pullup (bus); endmodule

多个驱动同时挂在一条 net 上时,最终值由裁决表决定,规则在第 2 章提过,这里给全:

驱动 A 给出 驱动 B 给出 线上结果
0 0 0
1 1 1
0 1 x(冲突)
0 或 1 z 由 A 决定(z 让位)
z z z(无人驱动)

规则的核心是两条:z 让位(高阻不算意见),异值冲突出 x。pullup、pulldown 提供弱驱动,强驱动在场时弱驱动让位——这给了总线一个「默认值」机制:所有驱动都关闭时,读总线得到 1 或 0 而不是悬空的 z,很多外设协议正是靠这个机制定义「总线空闲态」。

05-05-fig01-2

双向端口的建模

芯片引脚双向(inout)是三态总线最典型的应用场景。建模套路固定:引脚声明为 inout、内部拆成输出使能加输入两条路:

module bidir_pin( inout wire [7:0] dq, // 双向数据引脚 input wire we_n, // 写使能,低有效 input wire [7:0] dout_i, // 内部要发出去的数据 output wire [7:0] din_o // 内部收到的数据 ); // 输出方向:写使能有效时驱动引脚,否则放手 bufif1 drv(dq, dout_i, ~we_n); // 输入方向:引脚值永远可读 assign din_o = dq; endmodule

三条纪律必须守住。第一,内部逻辑绝不读自己正在驱动的总线——写期间引脚上是自己的值,读没有意义还容易吃冲突 x;需要回读验证时序,交给专门的总线仿真模型。第二,驱动使能的互斥靠设计保证,语言只裁决不强制,两个使能同时有效而数据相异,线上就是 x。第三,inout 不能出现在综合层次内部的模块间——FPGA 与 ASIC 的内部互连没有三态线,工具遇到内部 inout 要么报错要么强行改造,双向引脚只存在于顶层与物理引脚之间。芯片内部要共享一根线,用多路选择器:多个源各占一级选择,语义同样是「轮流发言」,却完全在同步逻辑掌控之内。

案例展开:总线上读回 x 的侦破。 背景:某系统与外部存储器联调,读操作偶发全 x。操作:分三步排——先看存储器片选与输出使能时序,确认存储器已驱动总线;再看本地控制器,发现读窗口内本地双向引脚的输出使能没有关干净(写使能释放沿与读采样沿间隔过近,本地还在驱动旧数据),本地驱动值与存储器驱动值冲突,裁决出 x。结果:把方向切换做成寄存器化的两拍动作(先关驱动、下一拍再读),冲突消失。解读:这类案子的本质是「两个驱动源的交接班没有空档」——三态总线的方向切换必须留出「双方都放手」的死区,硬件如此、协议如此、建模也如此。变式:无法改动方向切换时序的场合,在读路径上加一级寄存器配合使能延迟检查,用仿真断言盯住「读窗口内本地驱动必须无效」,把死区要求变成机器可查的规矩。

三态的现代定位

坦率地说,三态建模在今天 RTL 工作里的份额很小:FPGA 内部不支持三态、ASIC 内部不用三态,它的舞台只剩顶层引脚建模与板级系统仿真。但理解三态仍有独立价值——裁决表是「多驱动」概念的完整标本,第 2 章的类型裁决规则在这里全部落地;而「内部用选择器、顶层用三态」这条边界,是综合工具支持差异的活教材。评审老代码见到内部三态,应当作迁移风险项登记。

常见疑问三则

问:pullup 挂了但总线空闲时读到 0,为什么

先查强度:pullup 是弱驱动,若某个本应关闭的三态门没有完全关闭(建模错误或使能条件写反),强驱动会压过弱上拉。再查裁决表:两个弱驱动异值也会冲突出 x。排查工具是仿真里按强度显示的波形视图,普通波形视图看不到强度差异,容易误判。

问:双向总线的读回校验怎么做才对

不要在读自己驱动的窗口内校验。正确做法是分时:驱动期只写,释放后的窗口才读回并比对。若协议必须即写即读,用独立的输出副本信号做期望值比对,而不是读总线本身——总线上是裁决结果,副本上才是你的真实意图,两者在冲突时刻并不相等,而你想查的是「我发了什么」加「对方回什么」,不是「线上的仲裁结果」。

问:评审时怎么快速识别内部三态

全库检索三态门实例化与 inout 端口声明,命中即逐个确认位置:顶层引脚文件里的合法,层次内部的登记为迁移风险项。这个检查可以做成 Lint 规则自动化,规则逻辑简单(扫描关键字),收益却很高——内部三态是平台迁移时最先爆的问题之一。

本节要点回顾

  • 三态门四兄弟:按使能电平与是否反相命名,使能无效即输出 z 放手;
  • 裁决表两条核心:z 让位、异值冲突出 x,pullup 提供弱默认值;
  • 双向引脚套路固定:inout 引脚、输出 bufif、输入直连,内部逻辑不读自己驱动的线;
  • 使能互斥靠设计:语言只裁决不强制,方向切换必须留双方放手的死区;
  • 内部禁三态:FPGA 与 ASIC 内部互连没有三态线,共享一根线用多路选择器;
  • 现代定位:舞台在顶层引脚与板级仿真,理解它是为了裁决规则与工具边界。

现场重建完毕,电路的物理长相已经心中有数。下一章回到工程最常见的惯犯:状态机、生成语句与跨时钟域——RTL 层真正考验功力的三件事。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U