三态(tri-state)门、双向(bi-directional)端口的建模、仿真和综合

article/2025/9/17 23:44:54

目录

1. 概要

2. 三态门 

2.1 概念

2.2 三态门建模

3. 双向端口

3.1 HDL语言描述

3.2 直接调用元件库中的模块

3. 仿真

4. 综合


1. 概要

        双向端口顾名思义是一种既可以作为输入端口接收数据,也可以作为输出端口发出数据,它对数据的操作是双向的。比如某个设计需要一个 16 位的数据输入口和一个16 位的数据输出口,并且数据输入和输出不会同时发生。 如果数据输入口和输出口分别设计则需要32根数据线,而用双向端口来设计,则只需要16根数据线,这样就节省了16根数据线引脚。在很多情况下,芯片端口是宝贵的设计资源,而且芯片间的连线少对于板级设计也非常有利。因此,双向端口常用于芯片间需要进行半双工双向通信的场合,可以节省一半芯片端口以及减少板上芯片间连接的走线。

        常见的一些例子有:

        . I2C总线中的SDA信号线

        . AXI总线中的数据线

        . JESD207接口中的数据线DIQ、等等

        在电路层面,双向端口是通过三态缓冲器(也称三态门)控制实现的。在数字电路中,逻辑输出有两个正常态:低电平状态(逻辑0)和高电平状态(逻辑1),此外,电路还有不属于01的高阻态(逻辑Z)。所谓高阻,即输出端处于浮空状态,只有很小的漏电流流动,其电平随外部电平的高低而定,门电平放弃对输出电路的控制,或者可以理解为输出和电路是断开的。

2. 三态门 

2.1 概念

        在数字电路中,逻辑输出有两个正常态:低电平状态(对应逻辑0)和高电平状态(对应逻辑1);此外,电路还有不属于0和1状态的高阻态(对应逻辑Z  )。所谓高阻,即输出端属于浮空状态,只有很小的漏电流流动,其电平随外部电平高低而定,门电平放弃对输出电路的控制。或者可以理解为输出与电路是断开的。最基本的三态缓冲器的逻辑符号如下图:

        当OE为高电平时,Dataout与Datain相连,数据流向是从Datain向Dataout;而OE为低时,Dataout为高阻态,相当于与Datain之间的连线断开,此时可以从外部向Dataout驱动信号,实现相反方向的数据流向。

2.2 三态门建模

        三态门的RTL描述方式有以下两种等价的方式。

// Tristate Description Using Combinatorial Always Block
// File: tristates_1.v
//module tristates_1 (OE, I, O);input  OE, I;
output O;
reg    O;always @(OE or I)
beginif (OE)O = I;elseO = 1'bZ;
endendmodule
// Tristate Description Using Concurrent Assignment
// File: tristates_2.v
//module tristates_2 (OE, I, O);input  T, I;
output O;assign O = (OE) ? I: 1'bZ;endmodule

3. 双向端口

        通常两种双向端口建模的方法。

        第一种是直接用HDL语言进行行为级描述,基于以上三态门的RTL描述,稍作修改即可。另一种则是直接调用元件库(cell library)中的模块,比如说Xilinx FPGA中的IOBUF等。后者通常只用于在纯粹的FPGA开发(即FPGA实现就是最终实现)中,在芯片开发中,应该采用第一种,如果采用第二种描述的话,将会导致FPGA综合代码与芯片实现代码不一致,并导致FPGA原型验证的有效性受损,这是应该尽量避免的。

3.1 HDL语言描述

        以下为双向端口的两个行为级描述的module例。其中第一个有时钟控制,以同步于时钟沿的方式工作,第二个是存粹的组合逻辑描述方式。前者从综合时序的角度来说会更好一些。

module BIDIR_CLKED
#(parameter    P_WIDTH   = 6'd1       //  
)
(
input                CLK  ,
input                OE   ,     // 1: Output port; 0: Input port
input  [P_WIDTH-1:0] DIN  ,
output [P_WIDTH-1:0] DOUT ,
inout  [P_WIDTH-1:0] BIDIR
);reg     [P_WIDTH-1:0] din_reg;
reg     [P_WIDTH-1:0] dout_reg;assign BIDIR = OE ? din_reg : {P_WIDTH{1'bZ}};
assign DOUT  = dout_reg;// Pipelining
always @ (posedge CLK)
begindin_reg <= DIN;dout_reg <= BIDIR;        
endendmodule
module BIDIR
#(parameter    P_WIDTH   = 6'd1       //  
)
(
input                CLK    ,
input                OE     , // 1: Output port; 0: Input port
input  [P_WIDTH-1:0] DIN    ,
output [P_WIDTH-1:0] DOUT   ,
inout  [P_WIDTH-1:0] BIDIREC
);assign BIDIREC = OE ? DIN : {P_WIDTH{1'bZ}}; // DIN --> BIDIREC
assign DOUT    = {P_WIDTH{~OE}} & BIDIREC;   // BIDIREC --> DOUTendmodule

3.2 直接调用元件库中的模块

        不管是FPGA还是ASIC其标准单元库中通常都会包含双向端口单元。以Xilinx为例,它提供了IOBUF单元(另外,还有IOBUF_DIFF_OUT、IOBUFDS等),IOBUF的符号、真值表如下所示(参见UG768):

         以下是两个直接实例化IOBUF的代码例。第一个是1比特的双向端口的IOBUF实例化;第二个是一个多比特的双向总线模块,在该模块中实例化了多个IOBUF。

3. 仿真

        以下案例取自于一个实际的JESD207接口设计,JESD207接口中DIQ信号线是双向信号线。上半部分代码是DUT中实例化BIDIR_CLKED实现双向端口JESD207.DIQ;下半部分为testbench中的处理。

// ***************************************************************************
//BIDIR instantiation in DUT 
wire [11:0] diq_tx; 
wire [11:0] diq_rx;
assign diq_rx = ...; 
BIDIR_CLKED #(12) u_BIDIR_CLKED
(
.CLK    (CLK      ), 
.OE     (DIQ_OE   ),        // 0: RX; 1: TX
.DIN    (diq_tx   ),
.DOUT   (diq_rx   ),
.BIDIREC(DIQ      )        
);// ***************************************************************************
//Signal assignment in testbench.
logic diq_oe;        // Connect to DUT.DIQ_OE port
wire [11:0] tx_diq;
wire [11:0] rx_diq;
wire [11:0] diq;     // Connect to DUT.DIQ port
assign diq    = diq_oe ? {12{1'bZ}}: rx_diq;
assign tx_diq = diq;
// ***************************************************************************

        需要注意的是,在testbench中,对应于DIQ的信号需要定义成wire类型。此外,对于双向端口/信号的描述,在DUT和testbench中是互补的。如以上代码例所示,由当DUT.DIQ在DIQ_OE的控制下作为输出端口使用,testbench中则应该是要作为输入信号处理,即接收DUT输出的信号;反之,当DUT.DIQ在DIQ_OE的控制下作为输入端口使用,testbench中则应该是要作为输出信号处理,即对DIQ信号进行驱动赋值。

4. 综合

        如上所述,作为芯片设计的FPGA原型验证时,应该使用行为级的方式描述双向端口。但是如何确认描述是否正确呢?一般来说仿真当然可以在很大程度确认这一点,但是更为直接方式是针对综合生成电路进行直接确认,确认综合工具是否正确地将行为级描述正确地推断(infer)为IOBUF。

     以上所述的JESD207接口的Vivado综合为例,在综合结束后,从Vivado界面点击SynthesisàOpen Synthesized DesignàSchematic打开综合生成的电路图,可以找到如下图所示的对应JESD_DIQ接口电路图。从图中可以明确地看出JESD207接口的DIQ端口被正确地推断为IOBUF。

        不管用BIDIR还是用BIDIR_CLKED都可以综合得出以上结果。        

        芯片综合工具通常也提供查看综合后电路的功能,可以以相同的方式进行直接确认。

参考文献

[1] Tristates • Vivado Design Suite User Guide: Synthesis (UG901) 


http://chatgpt.dhexx.cn/article/4YsMabZY.shtml

相关文章

FPGA基础知识极简教程(8)详解三态缓冲器

博文目录 写在前面正文 全双工与半双工FPGA和ASIC中的三态缓冲器如何在VHDL和Verilog中推断出三态缓冲区 参考资料交个朋友 写在前面 下面用举例子的方式引出三态门&#xff0c;内容过长&#xff0c;大家可直接跳过&#xff0c;进入正文&#xff01; 三态门在FPGA以及ASIC设计中…

三态缓冲器的工作原理

转载自---百家号 三态缓冲器&#xff08;Three-state buffer&#xff09;&#xff0c;又称为三态门、三态驱动器&#xff0c;其三态输出受到使能输出端的控制&#xff0c;当使能输出有效时&#xff0c;器件实现正常逻辑状态输出&#xff08;逻辑0、逻辑1&#xff09;&#xff…

VSCODE调试时在cygwin.S中发生段错误

起因&#xff1a; C实现矩阵类和向量类 当看了我实现的矩阵类后&#xff0c;一个同学问我&#xff1a; 然后我就试了试1000维&#xff0c;结果运行时在cygwin.S里引发了奇奇怪怪的Segmentation fault&#xff0c;而且这个文件还是一片空白&#xff0c;压根就没有代码 后来一番…

【高并发】高并发环境下如何优化Tomcat性能?看完我懂了!

写在前面 Tomcat作为最常用的Java Web服务器&#xff0c;随着并发量越来越高&#xff0c;Tomcat的性能会急剧下降&#xff0c;那有没有什么方法来优化Tomcat在高并发环境下的性能呢&#xff1f; Tomcat运行模式 Tomcat的运行模式有3种。 1.bio模式 默认的模式,性能非常低下,…

Java-JVM-常用参数和调优方案(超保姆级)

Java-JVM-常用参数和调优方案 必须了解的内容 必须看过Java-JVM基础(调优必须知道)知道JVM大概的情况,这篇文章我博客里有 堆区&#xff08;Java堆&#xff1a;所有的线程共享该区域&#xff09; 通过new的方式创建的对象(一个类的实例)、数组所占的空间。 非堆区&#xff1a…

嵌入式知识图谱WiKi(嵌入式开发/研发入门教程和路线图)

嵌入式知识图谱WiKi 作者将狼才鲸创建时间2022-02-18 因图床更新不方便&#xff0c;最新版请跳转到Gitee文档源文件仓库网址 才鲸 / 嵌入式知识图谱WiKi CSDN有图的文档阅读网址 嵌入式知识图谱WiKi Bilibili视频讲解网址&#xff08;待完成&#xff09; 才鲸嵌入式主页 一、概…

select、poll和epoll

select、poll和epoll 对select、poll、epoll了解得不多&#xff0c;下面是从《构建高性能Web站点》摘录下来的介绍&#xff0c;等以后真正接触到select、poll和epoll方面的开发再详细写一下使用上的区别。 select select最早于1983年出现在4.2BSD中&#xff0c;它通过一个sele…

Mysql 和 Postgresql(PGSQL) 对比

Mysql 和 Postgresql(PGSQL) 对比 转载自&#xff1a;http://www.oschina.net/question/96003_13994 PostgreSQL与MySQL比较 MySQL使用太广泛了&#xff0c;以至于我不得不将一些应用从mysql 迁移到postgresql, 很多开源软件都是以Mysql 作为数据库标准&#xff0c;并且以Mysq…

JVM系列之常用参数的查看和设置

JVM常用参数 参数名称含义默认值说明-Xms初始堆大小&#xff0c;等价于-XX:InitialHeapSize物理内存的1/64默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时&#xff0c;JVM就会增大堆直到-Xmx的最大限制.-Xmx最大堆大小&#xff0c;等价于-XX:MaxHeapSize物理内存的1/…

Tomcat内存调整和默认线程池调整

上线了很久的一个项目&#xff08;财政数据共享平台&#xff09;&#xff0c;由于领导要求&#xff0c;新来的同事就把新项目&#xff08;社保数据共享&#xff09;做在了该项目上&#xff0c;这就导致了许多的问题&#xff0c;先从日志说起&#xff0c;该同事把数据获取和传送…

lunix下修改tomcat的堆内存大小

修改tomcat的初始堆大小和最大堆大小 要添加在tomcat 的bin 下catalina.sh 里&#xff0c;位置cygwinfalse前 。注意引号要带上,红色的为新添加的. # OS specific support. $var _must_ be set to either true or false.JAVA_OPTS"-Xms256m -Xmx512m -Xss1024K -XX:Perm…

java对象内存布局和对象定位

目录 观察对象在内存中的存储布局 利用java agent 利用JOL工具 Java对象定位 直接指针寻址 间接寻址 JIT(Just In-Time Compiler&#xff09; c1、c2 编译线程 c1, c2编译器线程高CPU消耗 - 潜在的解决方案 使用字节码和汇编语言同步分析volatile&#xff0c;synchron…

【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南

目录标题 Valgrind 工具的安装 交叉编译Valgrind Valgrind 工具的作用Memcheck 内存泄漏检测工具常规检测&#xff08;程序结束后生成报告&#xff09;重要参数长时间运行的服务使报告输出至文件报告分析示例一分析\_示例一示例二分析\_示例二 Massif堆栈检测工具Massif的基本…

C/C++开发,无可避免的多线程(篇一).跨平台并发编程姗姗来迟

目录 一、编译环境准备 1.1 编译环境配置 1.2 先睹为快的c11多线程编程示例 二、c/c并发编程支持 2.1 进程与线程 2.2 c/c多线程的并发编程 2.3 c11以前的多线程支持 2.4 c11以后的多线程支持 2.5 线程与互斥锁 2.6 跨线程安全问题 三、认识c/c的thread 3.1 std::thread类 3…

windows利器之cygwin

好久没写文章了&#xff0c;诸事烦身&#xff0c;脱不开。。。 不想开虚拟机占内存&#xff0c;同时还想在windows下使用linux命令&#xff0c;那就是cygwin了 第一部分 去官网下一个exe https://cygwin.com/install.html 直接运行&#xff0c; 基本都是默认&#xff0c; …

spi时序图怎么分析,怎么看懂spi时序图

我做产品的时候&#xff0c;最怕就是做IIC和SPI的通信。 这两种协议时序哪怕是延时时间有误差&#xff0c;都有可能导致通信不上。 出现问题的时候&#xff0c;如果没设备也很难排查问题到底出在哪里。 有时候这个产品写好的时序程序&#xff0c;换一个单片机用同一个程序移植过…

怎么看懂单片机时序图?

本人没有上过单片机相关的专业课&#xff0c;是在《计算机系统结构》里遇见的时序图。由于看不懂加之老师没有专门讲&#xff0c;因此自行查阅了相关的视频和博客。&#xff08;参考视频已放在文末&#xff09; 网上资源贫瘠&#xff0c;不过我也不需要太过深入的知识。 大家…

UML系列——时序图(顺序图)

引言 用例图、类图、活动图、时序图之间是什么关系&#xff1f; 时序图有什么作用&#xff1f; 先来模拟一下三国演义的赤壁之战的时序图&#xff0c;先知道它到底长什么样子&#xff0c;再深入介绍&#xff1a; 小伙伴惊呆了&#xff0c;这样画战略图&#xff0c;一目了然&…

UML图之五——时序图

一、什么是时序图 序列图表示了系统在参与者互动执行某一个用例期间,系统内部的一群对象的协作情况。一个用例就对应一个时序图。序列图是对系统动态行为进行描述。用于用例分析和设计阶段。 二、对比 1、序列图和协作图 序列图跟协作图相似,两种图传递的意思是一样的。不…

浅谈时序图

前序&#xff1a; 这周基本都在肝txmini项目&#xff0c;不知道是不是我菜&#xff0c;总觉得难度还是挺高的&#xff0c;所以就没太多时间整理知识点了。 项目进展了快大半个月了&#xff0c;最后因为性能问题&#xff0c;我们还是选择重构原来的代码。准备用golang去重构原本…